server: Refactor async, works until givehand

parent 02b95030
...@@ -36,8 +36,7 @@ async def hello_world(): ...@@ -36,8 +36,7 @@ async def hello_world():
@router.get("/reset") @router.get("/reset")
async def reset( async def reset(
): ):
lobby.reset() return lobby.reset()
return "Done."
app.include_router(router) app.include_router(router)
......
import asyncio
import json import json
from typing import List, Dict, Optional from typing import List, Dict, Optional
...@@ -37,30 +38,48 @@ class LobbyManager(ClientManager): ...@@ -37,30 +38,48 @@ class LobbyManager(ClientManager):
def players_ready(self): def players_ready(self):
return [self.lobby[k] for k, m in self.metadata.items() if m.ready] return [self.lobby[k] for k, m in self.metadata.items() if m.ready]
async def new_player(self, player: Player, sid: str) -> str: def new_player(self, player: Player, sid: str) -> str:
self.lobby[player.name] = player self.lobby[player.name] = player
self.players.append(player)
self.metadata[player.name] = Metadata(sid=sid) self.metadata[player.name] = Metadata(sid=sid)
print(f"Added {player} to a lobby with {len(self.lobby)} players.") print(f"Added {player} to a lobby with {len(self.lobby)} players.")
return f"Bienvenu, {player}! Il y a {len(self.lobby)} joueurs en ligne." return f"Bienvenu, {player}! Il y a {len(self.lobby)} joueurs en ligne."
def wants_to_play(self, player: Player): def wants_to_play(self, player: Player):
"""
Notes that a player wants to play, starting a game if others too.
"""
self.metadata[player.name].ready = True self.metadata[player.name].ready = True
print(f"{player} ready to play! ({self.nb_ready} people ready)") print(f"Lobby | {player} wants to play!")
async def announces(self, player: Player, announce: Announce): ready = self.players_ready
# FIXME: Call this message on incoming "ANNOUNCE" return ready
async def maybe_start_game(self):
print("Should we start a game?")
ready = self.players_ready
if len(ready) > 1:
await self.start_game(ready)
print(f"Lobby: Game started. with {ready}.")
def just_announced(self, player: Player, announce: Announce):
meta = self.metadata[player.name] meta = self.metadata[player.name]
meta.last_announce = announce meta.last_announce = announce
meta.fresh_announce = True meta.fresh_announce = True
print(f"{player} ready to play! ({self.nb_ready} people ready)") print(f"{player} announced {announce}!")
async def start_game(self, players: Optional[List[Player]] = None, max_players=2):
if not players:
players = self.players_ready[:max_players]
game = Game(players, manager=self)
self.games.append(game)
def start_game(self, max_players=2):
players = self.players_ready[:max_players]
self.games.append(Game(players, manager=self))
for p in players: for p in players:
self.metadata[p.name].ready = False self.metadata[p.name].ready = False
print(f"Game started : {' vs '.join([p.name for p in players])}") print(f"Game started : {' vs '.join([p.name for p in players])}")
await game.new_game()
def reset(self): def reset(self):
players = len(self.players) players = len(self.players)
...@@ -72,27 +91,27 @@ class LobbyManager(ClientManager): ...@@ -72,27 +91,27 @@ class LobbyManager(ClientManager):
self.send(p, MessageToPlayer.Reset) self.send(p, MessageToPlayer.Reset)
self.sio.disconnect(m.sid) self.sio.disconnect(m.sid)
self.lobby.clear() self.lobby.clear()
self.players.clear()
self.metadata.clear() self.metadata.clear()
self.games.clear() self.games.clear()
print(f"Reset done, {players} players, {games} games.") print(f"Reset done, {players} players, {games} games.")
return msg return msg
def send(self, to: Player, message: MessageToPlayer, extra=None): async def send(self, to: Player, message: MessageToPlayer, extras=None):
data = {message: message.name} sid = self.metadata[to.name].sid
if extra: data = {"message": str(message.name)}
data["extra"] = extra if extras:
self.sio.send(message) data["extra"] = extras
pass
print(f"MSGOUT|{sid} ({to.name}), {data}")
await self.sio.emit('messageChannel', json.dumps(data), room=sid)
def handle_message(self, sid, data): async def handle_message(self, sid, data):
message = None message = None
extras = {"players": [p.name for p in self.players]} extras = {"players": [p.name for p in self.players]}
print(f"Lobby| Received message from {sid}: {data}.")
sender = self.which_player(sid) sender = self.which_player(sid)
if sender:
print(f"Lobby| Found sender: {sender.name}") print(f"MSGIN| {sid} ({sender.name}): {data}.")
for option in MessageFromPlayer: for option in MessageFromPlayer:
if option.value in data: if option.value in data:
...@@ -100,34 +119,44 @@ class LobbyManager(ClientManager): ...@@ -100,34 +119,44 @@ class LobbyManager(ClientManager):
if option == MessageFromPlayer.Waiting: if option == MessageFromPlayer.Waiting:
self.metadata[sender.name].ready = False self.metadata[sender.name].ready = False
print(f"MSG|Player {sender.name} waiting, while {extras} ready.") print(f"Lobby| Player {sender.name} waiting")
if len(self.players_ready) > 1: message = MessageToPlayer.ReadyToStart \
message = MessageToPlayer.ReadyToStart if len(self.players_ready) > 1 else MessageToPlayer.Waiting
elif option == MessageFromPlayer.Ready: elif option == MessageFromPlayer.Ready:
self.wants_to_play(player=sender) print(f"Lobby|Player {sender.name} ready")
print(f"MSG|Players ready: {extras}.") gamers = self.wants_to_play(player=sender)
if gamers:
print(f"Game ready! gamers={gamers}")
message = MessageToPlayer.NewGame
extras["playersPlaying"] = [p.name for p in gamers]
else:
print(f"Still alone ready!")
message = MessageToPlayer.ReadyToStart
extras["playersReady"] = [p.name for p in self.players_ready]
message = MessageToPlayer.ReadyToStart \
if len(self.players_ready) > 1 else MessageToPlayer.Waiting
extras["playersReady"] = [p.name for p in self.players_ready]
elif option == MessageFromPlayer.Bet: elif option == MessageFromPlayer.Bet:
# FIXME vraie annonce, pas juste carre d'as lol # FIXME vraie annonce, pas juste carre d'as lol
self.announces(player=sender, announce = Announce(bet=CARRE_ACE)
announce=Announce(bet=CARRE_ACE)) self.just_announced(player=sender,
game: Game = self.game_with(sender) announce=announce)
# TODO: connect with current game, return appropriate message
print(f"Lobby| Player {sender.name} just announced {announce}.")
extras["youBet"] = announce.bet
elif option == MessageFromPlayer.Menteur: elif option == MessageFromPlayer.Menteur:
self.announces(player=sender, announce=Announce()) self.just_announced(player=sender, announce=Announce())
# TODO: connect with current game, return appropriate message extras["youBet"] = False
body = {"message": message.name if message else "none"} if message:
if extras: game = asyncio.create_task(self.maybe_start_game())
body["extras"] = extras await self.send(sender, message, extras)
return json.dumps(body) await game
def which_player(self, sid) -> Player: def which_player(self, sid) -> Player:
sender: Optional[Player] = None sender: Optional[Player] = None
...@@ -139,8 +168,8 @@ class LobbyManager(ClientManager): ...@@ -139,8 +168,8 @@ class LobbyManager(ClientManager):
def game_with(self, player: Player) -> Game: def game_with(self, player: Player) -> Game:
return [g for g in self.games if player in g.players][0] return [g for g in self.games if player in g.players][0]
def send_waiting_for(self, player: Player): async def send_waiting_for(self, player: Player):
game = self.game_with(player) game = self.game_with(player)
self.send(player, MessageToPlayer.YourTurn, extra={"bet": game.current_bet}) await self.send(player, MessageToPlayer.YourTurn, extras={"bet": game.current_bet})
for p in [p for p in game.players if p != player]: for p in [p for p in game.players if p != player]:
self.send(p, MessageToPlayer.Waiting, extra={"waitingFor": p.name}) await self.send(p, MessageToPlayer.Waiting, extras={"waitingFor": p.name})
...@@ -19,7 +19,7 @@ class ClientManager(ABC): ...@@ -19,7 +19,7 @@ class ClientManager(ABC):
self.send(p, message) self.send(p, message)
@abstractmethod @abstractmethod
def send(self, async def send(self,
to: Player, to: Player,
message: MessageToPlayer, message: MessageToPlayer,
extra=None): extra=None):
......
...@@ -25,7 +25,7 @@ class Game: ...@@ -25,7 +25,7 @@ class Game:
self.current_bet: Optional[Hand] = None self.current_bet: Optional[Hand] = None
self.manager = manager self.manager = manager
def message(self, message: MessageToPlayer, async def message(self, message: MessageToPlayer,
*to: Player, *to: Player,
extra=None extra=None
) -> None: ) -> None:
...@@ -33,7 +33,7 @@ class Game: ...@@ -33,7 +33,7 @@ class Game:
if not to: if not to:
to = self.players to = self.players
for player in to: for player in to:
self.manager.send(player, message, extra) await self.manager.send(player, message, extra)
@property @property
def global_hand(self) -> Hand: def global_hand(self) -> Hand:
...@@ -41,6 +41,7 @@ class Game: ...@@ -41,6 +41,7 @@ class Game:
return Hand(cards=all_cards) return Hand(cards=all_cards)
async def new_game(self): async def new_game(self):
print(f"Game starting with {self.players}!")
self.deck.reset() self.deck.reset()
while len(self.players) > 1: while len(self.players) > 1:
...@@ -48,14 +49,14 @@ class Game: ...@@ -48,14 +49,14 @@ class Game:
if self.defeats[loser] == 5: if self.defeats[loser] == 5:
print(f"{loser} is eliminated!") print(f"{loser} is eliminated!")
self.message(MessageToPlayer.Lose, loser) await self.message(MessageToPlayer.Lose, loser)
self.players.remove(loser) self.players.remove(loser)
else: else:
print(f"{loser} lost the round, now playing with {self.defeats[loser] + 1} cards!") print(f"{loser} lost the round, now playing with {self.defeats[loser] + 1} cards!")
winner = self.players[0] winner = self.players[0]
self.message(MessageToPlayer.Win, winner) await self.message(MessageToPlayer.Win, winner)
self.message(MessageToPlayer.WinnerIs, extra=winner) await self.message(MessageToPlayer.WinnerIs, extra=winner)
print(f"Game over - {winner.name} wins with {len(winner.hand)} cards!") print(f"Game over - {winner.name} wins with {len(winner.hand)} cards!")
async def new_turn(self) -> Player: async def new_turn(self) -> Player:
...@@ -67,7 +68,7 @@ class Game: ...@@ -67,7 +68,7 @@ class Game:
# Distribution # Distribution
self.deck.reset() self.deck.reset()
self.message(MessageToPlayer.WaitTurn) await self.message(MessageToPlayer.WaitTurn)
for current_player in self.players: for current_player in self.players:
current_player.clear() current_player.clear()
count_player_cards = self.defeats[current_player] + 1 count_player_cards = self.defeats[current_player] + 1
...@@ -77,7 +78,7 @@ class Game: ...@@ -77,7 +78,7 @@ class Game:
current_player.give(card) current_player.give(card)
print(f"{card}") print(f"{card}")
self.message(MessageToPlayer.GiveHand, current_player, extra=current_player.hand) await self.message(MessageToPlayer.GiveHand, current_player, extra=current_player.hand)
print(f"Cards sent.") print(f"Cards sent.")
# Tour # Tour
...@@ -88,7 +89,7 @@ class Game: ...@@ -88,7 +89,7 @@ class Game:
if loser is not None: if loser is not None:
self.players.remove(loser) self.players.remove(loser)
self.players.insert(0, loser) self.players.insert(0, loser)
self.message(MessageToPlayer.LoseRound, extra=loser.name) await self.message(MessageToPlayer.LoseRound, extra=loser.name)
return loser return loser
last_player = current_player last_player = current_player
...@@ -142,14 +143,14 @@ class Game: ...@@ -142,14 +143,14 @@ class Game:
print(f"| {current_player}'s turn >") print(f"| {current_player}'s turn >")
if not self.current_bet: # First player, has to bet something if not self.current_bet: # First player, has to bet something
self.message(MessageToPlayer.YourTurn, current_player, extra=self.current_bet) await self.message(MessageToPlayer.YourTurn, current_player, extra=self.current_bet)
while not self.current_bet: # Ask a valid bet while not self.current_bet: # Ask a valid bet
# FIXME: Wait for player announce? Maybe just sleep 10? # FIXME: Wait for player announce? Maybe just sleep 10?
announce = await current_player.announce(self.current_bet) announce = await current_player.announce(self.current_bet)
if announce.bet: if announce.bet:
self.current_bet = announce.bet self.current_bet = announce.bet
print(f"{current_player} starts the round: {self.current_bet}") print(f"{current_player} starts the round: {self.current_bet}")
self.message(MessageToPlayer.Announce, extra={"player": current_player, "announce": announce}) await self.message(MessageToPlayer.Announce, extra={"player": current_player, "announce": announce})
else: else:
print(f"You cannot say Menteur on first round, {current_player}!") print(f"You cannot say Menteur on first round, {current_player}!")
...@@ -160,7 +161,7 @@ class Game: ...@@ -160,7 +161,7 @@ class Game:
print("CARRE D'AS!") print("CARRE D'AS!")
announce = Announce() # MENTEUR obligatoire announce = Announce() # MENTEUR obligatoire
else: else:
self.message(MessageToPlayer.YourTurn, current_player, extra=self.current_bet) await self.message(MessageToPlayer.YourTurn, current_player, extra=self.current_bet)
announce = current_player.announce(self.current_bet) announce = current_player.announce(self.current_bet)
if announce.bet: if announce.bet:
......
...@@ -3,8 +3,7 @@ from typing import Optional ...@@ -3,8 +3,7 @@ from typing import Optional
import socketio import socketio
from server.game.lobby import LobbyManager from server.game.lobby import LobbyManager, Metadata
from server.game.message import MessageToPlayer
from server.model.hand import Hand from server.model.hand import Hand
from server.model.players import Player, Announce from server.model.players import Player, Announce
...@@ -23,34 +22,38 @@ class ClientPlayer(Player): ...@@ -23,34 +22,38 @@ class ClientPlayer(Player):
self.ready = False self.ready = False
async def announce(self, current_bet: Optional[Hand]) -> Announce: async def announce(self, current_bet: Optional[Hand]) -> Announce:
announce = None metadata: Metadata = self.lobby.metadata[self.name]
while not self.lobby.metadata[self.name].fresh_announce: print(f"Asking Client {self.name} for announce...", end="")
lobby.send_waiting_for(self)
while not metadata.last_announce and metadata.fresh_announce:
await lobby.send_waiting_for(self)
print(".", end="")
sleep(2) sleep(2)
return lobby.last_announces[self]
print(f" {metadata.last_announce.bet}!")
return metadata.last_announce
@sio.event @sio.event
async def connect(sid, environ): async def connect(sid, environ):
print("[WS] Connect ", sid, environ) print("[WS] Connect ", sid, environ)
player = ClientPlayer(lobby) player = ClientPlayer(lobby)
reply: str = await lobby.new_player(player, sid) reply: str = lobby.new_player(player, sid)
await sio.emit('messageChannel', reply, room=sid) await sio.emit('messageChannel', reply, room=sid)
@sio.event @sio.event
async def message(sid, data): async def message(sid, data):
print("[WS] Message ", data) print("[WS] Message ", data)
await sio.emit('messageChannel', lobby.handle_message(sid, data), room=sid) await lobby.handle_message(sid, data)
@sio.on("pingServer") @sio.on("pingServer")
async def ping_server(sid, data): async def ping_server(sid, data):
print("[WS] Ping received:", data) print("[WS] Ping received:", data)
await sio.emit('messageChannel', "PONG") await sio.emit('messageChannel', "PONG", room=sid)
@sio.event @sio.event
def disconnect(sid): def disconnect(sid):
print('[WS] Disconnect ', sid) print('[WS] Disconnect ', sid)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment