Skip to content

Commit 7e4e50a

Browse files
added typing for participants
1 parent 89308d5 commit 7e4e50a

File tree

2 files changed

+44
-38
lines changed

2 files changed

+44
-38
lines changed

src/model/multideck.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737

3838

3939
class MultiDeck(Generic[T, U]):
40-
"""One (refilling) deck used to make selection seem more 'random'."""
40+
"""A (refilling) deck used to make selection seem more 'random'."""
4141

4242
def __init__(self, deck: List[T]) -> None:
4343
"""Constructor.

src/model/participant.py

Lines changed: 43 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -29,23 +29,29 @@
2929
from copy import deepcopy
3030
from threading import RLock
3131
from time import time
32+
from typing import Dict, List, Mapping, Optional, Set, TYPE_CHECKING, Union
3233

3334
from 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+
3642
class 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

Comments
 (0)