1def чукай(part):
2 def decorator(func):
3 def wrapper(self, other):
4 winner = None
5 broken_part = f"_broken_{part}"
6 if getattr(self, broken_part) or getattr(other, broken_part):
7 raise TypeError(f"Счупена част: {part}")
8 if not isinstance(other, Egg):
9 raise AttributeError("Чукане само на две яйца")
10 self_stren = self.calculate_strength(part)
11 other_stren = other.calculate_strength(part)
12 if self_stren > other_stren:
13 setattr(other, broken_part, True)
14 winner = self
15 else:
16 setattr(self, broken_part, True)
17 winner = other
18
19 if hasattr(self, "registered") and self._tournament:
20 self.registered._record_battle(self, other, part, winner)
21
22 return winner
23 return wrapper
24 return decorator
25
26class Egg:
27 def __init__(self):
28 self._colors = []
29 self._fullness = 0.0
30 self._broken_top = False
31 self._broken_bottom = False
32 self.registered = None
33
34 def paint(self, *args):
35 sum_percentages = sum(pair[1] for pair in args)
36 if sum_percentages + self._fullness > 100.00:
37 raise ValueError("Egg color is full")
38
39 for color, percentage in args:
40 self._colors.append((color.upper(), percentage))
41 self._fullness += sum_percentages
42
43 def get_color_value(self, hex_color):
44 """Преобразуване от 16-тична в инт"""
45 r_value = int(hex_color[0:2], 16)
46 g_value = int(hex_color[2:4], 16)
47 b_value = int(hex_color[4:6], 16)
48 return r_value + g_value + b_value
49
50 def calculate_strength(self, part):
51 strength = 0.0
52 curr_coverage = 0.0
53 curr_perc = 0.0
54
55 if part == "top":
56 left_index = 0.0
57 right_index = 50.0
58 else:
59 left_index = 50.0
60 right_index = 100.0
61
62 for pair in self._colors:
63 starting_point = curr_perc
64 ending_point = curr_perc + pair[1]
65 overal_egg_start = max(starting_point, left_index)
66 overall_egg_end = min(ending_point, right_index)
67 if overal_egg_start < overall_egg_end:
68 partitial_perc = overall_egg_end - overal_egg_start
69 strength += partitial_perc * self.get_color_value(pair[0])
70 curr_coverage += partitial_perc
71 curr_perc = ending_point
72 return (strength, curr_coverage)
73
74 @чукай("top")
75 def __mul__(self, other):
76 pass
77
78 @чукай("bottom")
79 def __matmul__(self, other):
80 pass
81
82
83class EggTournament:
84 def __init__(self):
85 #self.tournament_name
86 self._participants = {}
87 self._egss_in = {}
88 self._battles = {}
89 self._record = {}
90
91 def register(self, egg, pseudo):
92 if not isinstance(egg, Egg):
93 raise AttributeError("Only eggs allowed in tournament")
94 if egg.registered:
95 raise ValueError("An egg cannot be registered in multiple tournaments")
96 if pseudo in self._participants.keys():
97 raise ValueError(f"Egg with name {pseudo} has already been registered")
98 if not pseudo.isidentifier():
99 raise ValueError("Invalid registration name")
100
101 self._participants[pseudo] = egg
102 self._egss_in[egg] = pseudo
103 egg.registered = self
104 self._record[egg] = 0
105
106 def _record_battle(self, egg1, egg2, part, winner):
107 if egg1 in self._egss_in and egg2 in self._egss_in:
108 battle_key = (frozenset([egg1, egg2]), part) #имах много ядове с това и накрая ai ми помогна с frozenset - признат грях, половин грях
109 self._battles[battle_key] = winner
110 self._record[winner] += 1
111
112 def __contains__(self, egg):
113 return egg in self._egss_in
114
115 def __getitem__(self, battle):
116 if isinstance(battle, slice):
117 egg1 = battle.start
118 egg2 = battle.stop
119 part = battle.step
120 else:
121 egg1 = battle[0]
122 egg2 = battle[1]
123 part = battle[2]
124
125 battle_key = (frozenset([egg1, egg2]), part)
126 if battle_key in self._battles:
127 return self._battles[battle_key]
128 raise KeyError("No such match in tournament history")
129
130 def __getattr__(self, name):
131 if name in self._participants:
132 egg = self._participants[name]
133 res = {}
134 res["position"] = self._get_rank(egg)
135 res["victories"] = self._record[egg]
136 return res
137 raise AttributeError("Apologies, there is no such egg registered")
138
139 def _get_record(self, egg):
140 return self._record[egg]
141
142 def _rank_eggs(self):
143 if not self._participants:
144 return {}
145 eggs = []
146 for egg in self._participants.values():
147 eggs.append(egg)
148
149 eggs.sort(key=self._get_record, reverse=True)
150 ranking = {}
151 curr_pos = 0
152 prev_win_cnt = -1
153 for egg in eggs:
154 wins = self._record[egg]
155 if wins != prev_win_cnt:
156 curr_pos += 1
157 ranking[egg] = curr_pos
158 prev_win_cnt = wins
159 return ranking
160
161 def _get_rank(self, egg):
162 return self._rank_eggs().get(egg)
163
164 def __rmatmul__(self, rank):
165 if not isinstance(rank, int):
166 raise AttributeError("Ranks should be numbers")
167 ranks = self._rank_eggs()
168 curr_rank_winners = []
169 for egg in ranks:
170 if ranks[egg] == rank:
171 curr_rank_winners.append(egg)
172 if len(curr_rank_winners) == 0:
173 raise IndexError(f"No eggs at rank {rank}")
174 elif len(curr_rank_winners) == 1:
175 return curr_rank_winners[0]
176 return set(curr_rank_winners)
EEEEEEEEEEEEEE...EEEEEEEEE..E..E.EEEE.EEEE..EE
======================================================================
ERROR: test_bottom_collision_returns_egg_with_greater_bottom_strength (test.TestEgg.test_bottom_collision_returns_egg_with_greater_bottom_strength)
A bottom collision should return the egg with the greater bottom strength.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 177, in test_bottom_collision_returns_egg_with_greater_bottom_strength
self.assertIs(stronger_egg @ weaker_egg, stronger_egg)
~~~~~~~~~~~~~^~~~~~~~~~~~
File "/tmp/solution.py", line 19, in wrapper
if hasattr(self, "registered") and self._tournament:
^^^^^^^^^^^^^^^^
AttributeError: 'Egg' object has no attribute '_tournament'
======================================================================
ERROR: test_breaking_one_side_does_not_prevent_using_the_other_side (test.TestEgg.test_breaking_one_side_does_not_prevent_using_the_other_side)
Breaking one side of an egg should not prevent using the other side.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 287, in test_breaking_one_side_does_not_prevent_using_the_other_side
self.assertIs(first_egg * second_egg, second_egg)
~~~~~~~~~~^~~~~~~~~~~~
File "/tmp/solution.py", line 19, in wrapper
if hasattr(self, "registered") and self._tournament:
^^^^^^^^^^^^^^^^
AttributeError: 'Egg' object has no attribute '_tournament'
======================================================================
ERROR: test_broken_side_raises_type_error_regardless_of_operand_position (test.TestEgg.test_broken_side_raises_type_error_regardless_of_operand_position)
Using a broken side in a collision should raise a TypeError regardless of operand position.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 257, in test_broken_side_raises_type_error_regardless_of_operand_position
self.assertIs(broken_top_egg * top_winner, top_winner)
~~~~~~~~~~~~~~~^~~~~~~~~~~~
File "/tmp/solution.py", line 19, in wrapper
if hasattr(self, "registered") and self._tournament:
^^^^^^^^^^^^^^^^
AttributeError: 'Egg' object has no attribute '_tournament'
======================================================================
ERROR: test_collision_result_is_independent_of_operand_order (test.TestEgg.test_collision_result_is_independent_of_operand_order)
Swapping the egg operands should not change the collision winner.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 212, in test_collision_result_is_independent_of_operand_order
self.assertIs(top_first_egg * top_second_egg, top_first_egg)
~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~
File "/tmp/solution.py", line 19, in wrapper
if hasattr(self, "registered") and self._tournament:
^^^^^^^^^^^^^^^^
AttributeError: 'Egg' object has no attribute '_tournament'
======================================================================
ERROR: test_collision_with_partially_painted_eggs (test.TestEgg.test_collision_with_partially_painted_eggs)
Partially painted eggs should collide correctly from both sides.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 192, in test_collision_with_partially_painted_eggs
self.assertIs(first_egg * second_egg, first_egg)
~~~~~~~~~~^~~~~~~~~~~~
File "/tmp/solution.py", line 19, in wrapper
if hasattr(self, "registered") and self._tournament:
^^^^^^^^^^^^^^^^
AttributeError: 'Egg' object has no attribute '_tournament'
======================================================================
ERROR: test_failed_paint_overflow_does_not_change_egg_state (test.TestEgg.test_failed_paint_overflow_does_not_change_egg_state)
Failing to paint an egg because of overflow should not change its state.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 91, in test_failed_paint_overflow_does_not_change_egg_state
self.assertIs(reference_egg * reference_top_opponent, reference_egg)
~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
File "/tmp/solution.py", line 19, in wrapper
if hasattr(self, "registered") and self._tournament:
^^^^^^^^^^^^^^^^
AttributeError: 'Egg' object has no attribute '_tournament'
======================================================================
ERROR: test_losing_side_becomes_unusable (test.TestEgg.test_losing_side_becomes_unusable)
Losing a collision should make the losing side unusable.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 238, in test_losing_side_becomes_unusable
self.assertIs(top_loser * top_winner, top_winner)
~~~~~~~~~~^~~~~~~~~~~~
File "/tmp/solution.py", line 19, in wrapper
if hasattr(self, "registered") and self._tournament:
^^^^^^^^^^^^^^^^
AttributeError: 'Egg' object has no attribute '_tournament'
======================================================================
ERROR: test_paint_boundary_exactly_at_50_percent (test.TestEgg.test_paint_boundary_exactly_at_50_percent)
Painting an egg exactly to the half boundary should keep the two halves separate.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 130, in test_paint_boundary_exactly_at_50_percent
self.assertIs(egg * opponent, egg)
~~~~^~~~~~~~~~
File "/tmp/solution.py", line 19, in wrapper
if hasattr(self, "registered") and self._tournament:
^^^^^^^^^^^^^^^^
AttributeError: 'Egg' object has no attribute '_tournament'
======================================================================
ERROR: test_paint_can_be_called_multiple_times (test.TestEgg.test_paint_can_be_called_multiple_times)
Painting an egg in multiple calls should preserve the full painting order.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 54, in test_paint_can_be_called_multiple_times
self.assertIs(egg * top_opponent, egg)
~~~~^~~~~~~~~~~~~~
File "/tmp/solution.py", line 19, in wrapper
if hasattr(self, "registered") and self._tournament:
^^^^^^^^^^^^^^^^
AttributeError: 'Egg' object has no attribute '_tournament'
======================================================================
ERROR: test_paint_chunk_crossing_50_percent_boundary_is_split_correctly (test.TestEgg.test_paint_chunk_crossing_50_percent_boundary_is_split_correctly)
Painting a chunk across the half boundary should split it correctly between the two halves.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 138, in test_paint_chunk_crossing_50_percent_boundary_is_split_correctly
self.assertIs(egg * opponent, egg)
~~~~^~~~~~~~~~
File "/tmp/solution.py", line 19, in wrapper
if hasattr(self, "registered") and self._tournament:
^^^^^^^^^^^^^^^^
AttributeError: 'Egg' object has no attribute '_tournament'
======================================================================
ERROR: test_paint_exactly_to_100_percent_is_allowed (test.TestEgg.test_paint_exactly_to_100_percent_is_allowed)
Painting an egg exactly to 100 percent should not raise an error.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 41, in test_paint_exactly_to_100_percent_is_allowed
self.assertIs(egg @ opponent, egg)
~~~~^~~~~~~~~~
File "/tmp/solution.py", line 19, in wrapper
if hasattr(self, "registered") and self._tournament:
^^^^^^^^^^^^^^^^
AttributeError: 'Egg' object has no attribute '_tournament'
======================================================================
ERROR: test_paint_is_case_insensitive_for_hex_colors (test.TestEgg.test_paint_is_case_insensitive_for_hex_colors)
Painting an egg with lowercase and uppercase hex colors should produce the same behavior.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 111, in test_paint_is_case_insensitive_for_hex_colors
self.assertIs(lower_case_egg * lower_case_top_opponent, lower_case_egg)
~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
File "/tmp/solution.py", line 19, in wrapper
if hasattr(self, "registered") and self._tournament:
^^^^^^^^^^^^^^^^
AttributeError: 'Egg' object has no attribute '_tournament'
======================================================================
ERROR: test_paint_multiple_calls_can_cross_50_percent_boundary (test.TestEgg.test_paint_multiple_calls_can_cross_50_percent_boundary)
Painting an egg across the half boundary in multiple calls should split the halves correctly.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 150, in test_paint_multiple_calls_can_cross_50_percent_boundary
self.assertIs(egg * opponent, egg)
~~~~^~~~~~~~~~
File "/tmp/solution.py", line 19, in wrapper
if hasattr(self, "registered") and self._tournament:
^^^^^^^^^^^^^^^^
AttributeError: 'Egg' object has no attribute '_tournament'
======================================================================
ERROR: test_paint_order_of_color_chunks_matters (test.TestEgg.test_paint_order_of_color_chunks_matters)
Painting the same colors in different orders should change the collision result.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 122, in test_paint_order_of_color_chunks_matters
self.assertIs(first_egg * second_egg, first_egg)
~~~~~~~~~~^~~~~~~~~~~~
File "/tmp/solution.py", line 19, in wrapper
if hasattr(self, "registered") and self._tournament:
^^^^^^^^^^^^^^^^
AttributeError: 'Egg' object has no attribute '_tournament'
======================================================================
ERROR: test_paint_overflow_with_multiple_colors_should_not_change_the_egg (test.TestEgg.test_paint_overflow_with_multiple_colors_should_not_change_the_egg)
Failing to overpaint an egg with multiple colors should not change the egg.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 163, in test_paint_overflow_with_multiple_colors_should_not_change_the_egg
self.assertIs(egg @ bottom_opponent, bottom_opponent)
~~~~^~~~~~~~~~~~~~~~~
File "/tmp/solution.py", line 19, in wrapper
if hasattr(self, "registered") and self._tournament:
^^^^^^^^^^^^^^^^
AttributeError: 'Egg' object has no attribute '_tournament'
======================================================================
ERROR: test_paint_single_color_full_egg (test.TestEgg.test_paint_single_color_full_egg)
A fully painted single-color egg should win collisions against a weaker egg from both sides.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 30, in test_paint_single_color_full_egg
self.assertIs(egg * opponent, egg)
~~~~^~~~~~~~~~
File "/tmp/solution.py", line 19, in wrapper
if hasattr(self, "registered") and self._tournament:
^^^^^^^^^^^^^^^^
AttributeError: 'Egg' object has no attribute '_tournament'
======================================================================
ERROR: test_same_two_eggs_can_have_different_winners_for_top_and_bottom (test.TestEgg.test_same_two_eggs_can_have_different_winners_for_top_and_bottom)
The same two eggs should be able to have different winners for top and bottom collisions.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 184, in test_same_two_eggs_can_have_different_winners_for_top_and_bottom
self.assertIs(first_egg * second_egg, second_egg)
~~~~~~~~~~^~~~~~~~~~~~
File "/tmp/solution.py", line 19, in wrapper
if hasattr(self, "registered") and self._tournament:
^^^^^^^^^^^^^^^^
AttributeError: 'Egg' object has no attribute '_tournament'
======================================================================
ERROR: test_top_collision_returns_egg_with_greater_top_strength (test.TestEgg.test_top_collision_returns_egg_with_greater_top_strength)
A top collision should return the egg with the greater top strength.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 170, in test_top_collision_returns_egg_with_greater_top_strength
self.assertIs(stronger_egg * weaker_egg, stronger_egg)
~~~~~~~~~~~~~^~~~~~~~~~~~
File "/tmp/solution.py", line 19, in wrapper
if hasattr(self, "registered") and self._tournament:
^^^^^^^^^^^^^^^^
AttributeError: 'Egg' object has no attribute '_tournament'
======================================================================
ERROR: test_unpainted_half_loses_to_half_painted_black (test.TestEgg.test_unpainted_half_loses_to_half_painted_black)
An unpainted half should lose to a half painted in black.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 200, in test_unpainted_half_loses_to_half_painted_black
self.assertIs(unpainted_egg * black_egg, black_egg)
~~~~~~~~~~~~~~^~~~~~~~~~~
File "/tmp/solution.py", line 19, in wrapper
if hasattr(self, "registered") and self._tournament:
^^^^^^^^^^^^^^^^
AttributeError: 'Egg' object has no attribute '_tournament'
======================================================================
ERROR: test_winner_side_does_not_become_broken (test.TestEgg.test_winner_side_does_not_become_broken)
Winning a collision should not break the winning side.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 302, in test_winner_side_does_not_become_broken
self.assertIs(winner_egg * first_loser, winner_egg)
~~~~~~~~~~~^~~~~~~~~~~~~
File "/tmp/solution.py", line 19, in wrapper
if hasattr(self, "registered") and self._tournament:
^^^^^^^^^^^^^^^^
AttributeError: 'Egg' object has no attribute '_tournament'
======================================================================
ERROR: test_collision_between_registered_and_unregistered_egg_is_not_recorded (test.TestEggTournament.test_collision_between_registered_and_unregistered_egg_is_not_recorded)
A collision between a registered and an unregistered egg should not be recorded in the tournament.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 392, in test_collision_between_registered_and_unregistered_egg_is_not_recorded
self.assertIs(registered_egg * unregistered_egg, registered_egg)
~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
File "/tmp/solution.py", line 19, in wrapper
if hasattr(self, "registered") and self._tournament:
^^^^^^^^^^^^^^^^
AttributeError: 'Egg' object has no attribute '_tournament'
======================================================================
ERROR: test_collision_between_two_registered_eggs_is_recorded (test.TestEggTournament.test_collision_between_two_registered_eggs_is_recorded)
A collision between two registered eggs should be recorded in the tournament.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 371, in test_collision_between_two_registered_eggs_is_recorded
self.assertIs(first_egg * second_egg, first_egg)
~~~~~~~~~~^~~~~~~~~~~~
File "/tmp/solution.py", line 19, in wrapper
if hasattr(self, "registered") and self._tournament:
^^^^^^^^^^^^^^^^
AttributeError: 'Egg' object has no attribute '_tournament'
======================================================================
ERROR: test_collision_between_unregistered_eggs_is_not_recorded (test.TestEggTournament.test_collision_between_unregistered_eggs_is_not_recorded)
A collision between unregistered eggs should not be recorded in the tournament.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 381, in test_collision_between_unregistered_eggs_is_not_recorded
self.assertIs(first_egg * second_egg, first_egg)
~~~~~~~~~~^~~~~~~~~~~~
File "/tmp/solution.py", line 19, in wrapper
if hasattr(self, "registered") and self._tournament:
^^^^^^^^^^^^^^^^
AttributeError: 'Egg' object has no attribute '_tournament'
======================================================================
ERROR: test_egg_broken_outside_tournament_remains_broken_inside_tournament (test.TestEggTournament.test_egg_broken_outside_tournament_remains_broken_inside_tournament)
Breaking an egg outside the tournament should preserve its broken state inside the tournament.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 404, in test_egg_broken_outside_tournament_remains_broken_inside_tournament
self.assertIs(broken_egg * outsider, outsider)
~~~~~~~~~~~^~~~~~~~~~
File "/tmp/solution.py", line 19, in wrapper
if hasattr(self, "registered") and self._tournament:
^^^^^^^^^^^^^^^^
AttributeError: 'Egg' object has no attribute '_tournament'
======================================================================
ERROR: test_history_lookup_is_symmetric_with_respect_to_egg_order (test.TestEggTournament.test_history_lookup_is_symmetric_with_respect_to_egg_order)
Looking up a recorded collision in reversed egg order should return the same winner.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 445, in test_history_lookup_is_symmetric_with_respect_to_egg_order
self.assertIs(first_egg * second_egg, first_egg)
~~~~~~~~~~^~~~~~~~~~~~
File "/tmp/solution.py", line 19, in wrapper
if hasattr(self, "registered") and self._tournament:
^^^^^^^^^^^^^^^^
AttributeError: 'Egg' object has no attribute '_tournament'
======================================================================
ERROR: test_history_lookup_returns_winner_for_top_and_bottom (test.TestEggTournament.test_history_lookup_returns_winner_for_top_and_bottom)
Looking up recorded top and bottom collisions should return the correct winners.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 415, in test_history_lookup_returns_winner_for_top_and_bottom
self.assertIs(first_egg * second_egg, second_egg)
~~~~~~~~~~^~~~~~~~~~~~
File "/tmp/solution.py", line 19, in wrapper
if hasattr(self, "registered") and self._tournament:
^^^^^^^^^^^^^^^^
AttributeError: 'Egg' object has no attribute '_tournament'
======================================================================
ERROR: test_history_lookup_top_and_bottom_are_distinct (test.TestEggTournament.test_history_lookup_top_and_bottom_are_distinct)
Looking up top and bottom collisions should treat them as distinct entries.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 456, in test_history_lookup_top_and_bottom_are_distinct
self.assertIs(first_egg * second_egg, second_egg)
~~~~~~~~~~^~~~~~~~~~~~
File "/tmp/solution.py", line 19, in wrapper
if hasattr(self, "registered") and self._tournament:
^^^^^^^^^^^^^^^^
AttributeError: 'Egg' object has no attribute '_tournament'
======================================================================
ERROR: test_history_lookup_with_slice_key (test.TestEggTournament.test_history_lookup_with_slice_key)
Looking up a recorded collision with a slice key should return the winner.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 436, in test_history_lookup_with_slice_key
self.assertIs(first_egg * second_egg, first_egg)
~~~~~~~~~~^~~~~~~~~~~~
File "/tmp/solution.py", line 19, in wrapper
if hasattr(self, "registered") and self._tournament:
^^^^^^^^^^^^^^^^
AttributeError: 'Egg' object has no attribute '_tournament'
======================================================================
ERROR: test_history_lookup_with_tuple_key (test.TestEggTournament.test_history_lookup_with_tuple_key)
Looking up a recorded collision with a tuple key should return the winner.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 427, in test_history_lookup_with_tuple_key
self.assertIs(first_egg * second_egg, first_egg)
~~~~~~~~~~^~~~~~~~~~~~
File "/tmp/solution.py", line 19, in wrapper
if hasattr(self, "registered") and self._tournament:
^^^^^^^^^^^^^^^^
AttributeError: 'Egg' object has no attribute '_tournament'
======================================================================
ERROR: test_ranking_missing_position_raises_index_error (test.TestEggTournament.test_ranking_missing_position_raises_index_error)
Looking up a missing ranking position should raise an IndexError.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 533, in test_ranking_missing_position_raises_index_error
self.assertIs(alpha * beta, alpha)
~~~~~~^~~~~~
File "/tmp/solution.py", line 19, in wrapper
if hasattr(self, "registered") and self._tournament:
^^^^^^^^^^^^^^^^
AttributeError: 'Egg' object has no attribute '_tournament'
======================================================================
ERROR: test_ranking_tied_position_returns_set_of_eggs (test.TestEggTournament.test_ranking_tied_position_returns_set_of_eggs)
Looking up a tied ranking position should return a set of eggs.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 489, in test_ranking_tied_position_returns_set_of_eggs
self.assertIs(alpha * gamma, alpha)
~~~~~~^~~~~~~
File "/tmp/solution.py", line 19, in wrapper
if hasattr(self, "registered") and self._tournament:
^^^^^^^^^^^^^^^^
AttributeError: 'Egg' object has no attribute '_tournament'
======================================================================
ERROR: test_ranking_unique_position_returns_single_egg (test.TestEggTournament.test_ranking_unique_position_returns_single_egg)
Looking up a unique ranking position should return a single egg.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 477, in test_ranking_unique_position_returns_single_egg
self.assertIs(alpha * beta, alpha)
~~~~~~^~~~~~
File "/tmp/solution.py", line 19, in wrapper
if hasattr(self, "registered") and self._tournament:
^^^^^^^^^^^^^^^^
AttributeError: 'Egg' object has no attribute '_tournament'
======================================================================
ERROR: test_ranking_uses_dense_ranking_without_skipping_places (test.TestEggTournament.test_ranking_uses_dense_ranking_without_skipping_places)
Looking up ranking positions should use dense ranking without skipping places.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 509, in test_ranking_uses_dense_ranking_without_skipping_places
self.assertIs(alpha * beta, alpha)
~~~~~~^~~~~~
File "/tmp/solution.py", line 19, in wrapper
if hasattr(self, "registered") and self._tournament:
^^^^^^^^^^^^^^^^
AttributeError: 'Egg' object has no attribute '_tournament'
======================================================================
ERROR: test_registered_egg_attribute_returns_position_and_victories (test.TestEggTournament.test_registered_egg_attribute_returns_position_and_victories)
Accessing a registered egg as an attribute should return its position and victories.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 556, in test_registered_egg_attribute_returns_position_and_victories
self.assertIs(alpha * beta, alpha)
~~~~~~^~~~~~
File "/tmp/solution.py", line 19, in wrapper
if hasattr(self, "registered") and self._tournament:
^^^^^^^^^^^^^^^^
AttributeError: 'Egg' object has no attribute '_tournament'
======================================================================
ERROR: test_registered_egg_attribute_with_zero_victories_is_accessible (test.TestEggTournament.test_registered_egg_attribute_with_zero_victories_is_accessible)
Accessing a registered egg with zero victories should return its position and victories.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 572, in test_registered_egg_attribute_with_zero_victories_is_accessible
self.assertIs(alpha * beta, alpha)
~~~~~~^~~~~~
File "/tmp/solution.py", line 19, in wrapper
if hasattr(self, "registered") and self._tournament:
^^^^^^^^^^^^^^^^
AttributeError: 'Egg' object has no attribute '_tournament'
----------------------------------------------------------------------
Ran 46 tests in 0.011s
FAILED (errors=35)
Виктор Бечев
15.04.2026 14:15Имплементацията ти има един огромен проблем, и той е този ред:
```if hasattr(self, "registered") and self._tournament:```
Проблемът е, че `hasattr(self, "registered")` ще върне истина, дори `registered` да е `None` - `self.registered = None`. Предполагам само като четеш това ти става ясно защо. `hasattr` = има ли такъв атрибут. А не той истина ли е. И после става страшно, защоро нерегистрираните яйца нямат `self._tournament` и ти гърми с `AttributeError`.
Има няколко опции, които оправят проблема - `if getattr(self, "registered") ..` или пък `... and getattr(self, "_tournament", None)`.
Тъй като изрично сме казали, че дори и яйца, които не са регистрирани в даден турнир, трябва да могат да се чукат. И все пак, това е едно изискване от 20, не е редно това да ти струва много точки. При едно от горните решения би имал 31/46 теста, при другото - 35. И в двата случая това са 4/6 точки. За да не е безнаказана грешката ти, приемаме, че си -1 точка, и ти даваме бонус 2, така че да отговаря на реалните ти точки.
П.П. В момента не знаеш, че имаш 1 точка, и може би сметките изглеждат странно. Вече знаеш. И ще имаш 3. Освен ако не видя проблемен или страхотен код когато допрочета решението ти.
|
15.04.2026 14:21
15.04.2026 14:26
15.04.2026 14:27