2929from copy import deepcopy
3030from threading import RLock
3131from time import time
32+ from typing import Dict , List , Mapping , Optional , Set , TYPE_CHECKING , Union
3233
3334from nussschale .util .locks import mutex
3435
3536
37+ if TYPE_CHECKING :
38+ from model .match import Card
39+ from model .multideck import MultiDeck
40+
41+
3642class Participant :
3743 """Represents a participant in a match.
3844
3945 Attributes:
40- id (str) : The ID of the participant. Should not be changed once the
46+ id: The ID of the participant. Should not be changed once the
4147 participant is created.
42- nickname (str) : The nickname of the participant. Should not be changed.
43- picking (bool) : Whether the participant is picking.
44- score (int) : The score of the player. It is recommended to use the
48+ nickname: The nickname of the participant. Should not be changed.
49+ picking: Whether the participant is picking.
50+ score: The score of the player. It is recommended to use the
4551 provided modification method to prevent race conditions from
4652 occurring.
47- order (int) : The order key of the particpant, used for shuffling.
48- spectator (bool) : Whether the participant is a spectator.
53+ order: The order key of the particpant, used for shuffling.
54+ spectator: Whether the participant is a spectator.
4955 """
5056
5157 # The number of hand cards per type
@@ -54,12 +60,12 @@ class Participant:
5460 # The timeout timer after refreshing a participant, in seconds
5561 _PARTICIPANT_REFRESH_TIMER = 15
5662
57- def __init__ (self , id , nickname ) :
63+ def __init__ (self , id : str , nickname : str ) -> None :
5864 """Constructor.
5965
6066 Args:
61- id (str) : The player's ID.
62- nickname (str) : The nickname that will be used for the player.
67+ id: The player's ID.
68+ nickname: The nickname that will be used for the player.
6369 """
6470
6571 # MutEx for this participant
@@ -89,20 +95,20 @@ def __init__(self, id, nickname):
8995 self .spectator = False
9096
9197 # The hand of this participant
92- self ._hand = OrderedDict ()
98+ self ._hand = OrderedDict () # type: Dict[int, HandCard]
9399 self ._hand_counter = 1
94100
95- def has_timed_out (self ):
101+ def has_timed_out (self ) -> bool :
96102 """Checks whether this participant has timed out.
97103
98104 Returns:
99- bool: Whether this client has timed out.
105+ Whether this client has timed out.
100106 """
101107 # Locking is not needed here as access is atomic.
102108 return time () >= self ._timeout
103109
104110 @mutex
105- def increase_score (self ):
111+ def increase_score (self ) -> None :
106112 """Increases the score of this participant by one.
107113
108114 Contract:
@@ -111,13 +117,13 @@ def increase_score(self):
111117 assert not self .spectator , "Trying to increase score for spectator"
112118 self .score += 1
113119
114- def refresh (self ):
120+ def refresh (self ) -> None :
115121 """Refreshes the timeout timer of this participant."""
116122 # Locking is not needed here as access is atomic.
117123 self ._timeout = time () + Participant ._PARTICIPANT_REFRESH_TIMER
118124
119125 @mutex
120- def unchoose_all (self ):
126+ def unchoose_all (self ) -> None :
121127 """Unchooses all cards on the hand of this participant.
122128
123129 Contract:
@@ -128,58 +134,57 @@ def unchoose_all(self):
128134 hcard .chosen = None
129135
130136 @mutex
131- def delete_chosen (self ):
137+ def delete_chosen (self ) -> None :
132138 """Deletes all chosen hand cards from this participant.
133139
134140 Contract:
135141 This method locks the participant's lock.
136142 """
137143 assert not self .spectator , "Trying to delete for spectator"
138- del_list = []
144+ del_list = [] # type: List[int]
139145 for hid , hcard in self ._hand .items ():
140146 if hcard .chosen is not None :
141147 del_list .append (hid )
142148 for hid in del_list :
143149 del self ._hand [hid ]
144150
145151 @mutex
146- def get_hand (self ):
152+ def get_hand (self ) -> Dict [ int , "HandCard" ] :
147153 """Retrieves a snapshot of the hand of this participant.
148154
149155 Returns:
150- dict: A copy of the hand of the player.
156+ A copy of the hand of the player.
151157
152158 Contract:
153159 This method locks the participant's lock.
154160 """
155161 assert not self .spectator , "Trying to get hand for spectator"
156-
157162 return deepcopy (self ._hand )
158163
159164 @mutex
160- def choose_count (self ):
165+ def choose_count (self ) -> int :
161166 """Retrieves the number of chosen cards in the hand of this player.
162167
163168 Returns:
164- int: The number of cards in the hand.
169+ The number of cards in the hand.
165170
166171 Contract:
167172 This method locks the participant's lock.
168173 """
169174 assert not self .spectator , "Trying to get count for spectator"
170-
171175 n = 0
172176 for hcard in self ._hand .values ():
173177 if hcard .chosen is not None :
174178 n += 1
175179 return n
176180
177181 @mutex
178- def replenish_hand (self , mdecks ):
182+ def replenish_hand (self , mdecks : Mapping [str , "MultiDeck[Card, int]" ]
183+ ) -> None :
179184 """Replenishes the hand of this participant from the given decks.
180185
181186 Args:
182- mdecks (dict) : Maps card type to a multideck of the card type.
187+ mdecks: Maps card type to a multideck of the card type.
183188
184189 Contract:
185190 This method locks the participant's lock.
@@ -190,7 +195,7 @@ def replenish_hand(self, mdecks):
190195 for type in filter (lambda x : x != "STATEMENT" , mdecks ):
191196 # Count cards of that type and fetch IDs
192197 k_in_hand = 0
193- ids_banned = set ()
198+ ids_banned = set () # type: Set[int]
194199 for hcard in self ._hand .values ():
195200 if hcard .card .type == type :
196201 ids_banned .add (hcard .card .id )
@@ -206,12 +211,12 @@ def replenish_hand(self, mdecks):
206211 self ._hand_counter += 1
207212
208213 @mutex
209- def toggle_chosen (self , handid , allowance ) :
214+ def toggle_chosen (self , handid : int , allowance : int ) -> None :
210215 """Toggles whether the hand card with the given ID is chosen.
211216
212217 Args:
213- handid (int) : The ID of the hand card.
214- allowance (int) : The maximum number of cards that are allowed in
218+ handid: The ID of the hand card.
219+ allowance: The maximum number of cards that are allowed in
215220 the hand.
216221
217222 Contract:
@@ -243,21 +248,22 @@ def toggle_chosen(self, handid, allowance):
243248 other_hcard .chosen = None
244249
245250 @mutex
246- def get_choose_data (self , redacted ):
251+ def get_choose_data (self , redacted : bool
252+ ) -> List [Optional [Dict [str , Union [bool , str ]]]]:
247253 """Fetches the choose data for this participant.
248254
249255 Args:
250- redacted (bool) : Whether the information should be redacted.
256+ redacted: Whether the information should be redacted.
251257
252258 Returns:
253- list: The choose data for this participant.
259+ The choose data for this participant.
254260
255261 Contract:
256262 This method locks the participant's lock.
257263 """
258264 assert not self .spectator , "Trying to get data for spectator"
259265
260- data = []
266+ data = [] # type: List[Optional[Dict[str, Union[bool, str]]]]
261267 for hcard in self ._hand .values ():
262268 type = hcard .card .type
263269 text = hcard .card .text
@@ -276,17 +282,17 @@ class HandCard:
276282 """Represents a card on hand.
277283
278284 Attributes:
279- card (obj) : The card that this hand card represents. Should not be
285+ card: The card that this hand card represents. Should not be
280286 changed. Create a new HandCard if another card is required.
281- chosen (int, optional) : The choice index of this hand card. If the card
287+ chosen: The choice index of this hand card. If the card
282288 is not chosen it will be set to None.
283289 """
284290
285- def __init__ (self , card ) :
291+ def __init__ (self , card : "Card" ) -> None :
286292 """Constructor.
287293
288294 Args:
289295 card (obj): The card that this hand card represents.
290296 """
291297 self .card = card
292- self .chosen = None
298+ self .chosen = None # type: Optional[int]
0 commit comments