server: Refactor async, works until givehand

parent 02b95030
......@@ -36,8 +36,7 @@ async def hello_world():
@router.get("/reset")
async def reset(
):
lobby.reset()
return "Done."
return lobby.reset()
app.include_router(router)
......
import asyncio
import json
from typing import List, Dict, Optional
......@@ -37,30 +38,48 @@ class LobbyManager(ClientManager):
def players_ready(self):
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.players.append(player)
self.metadata[player.name] = Metadata(sid=sid)
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."
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
print(f"{player} ready to play! ({self.nb_ready} people ready)")
print(f"Lobby | {player} wants to play!")
ready = self.players_ready
return ready
async def announces(self, player: Player, announce: Announce):
# FIXME: Call this message on incoming "ANNOUNCE"
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.last_announce = announce
meta.fresh_announce = True
print(f"{player} ready to play! ({self.nb_ready} people ready)")
print(f"{player} announced {announce}!")
def start_game(self, max_players=2):
async def start_game(self, players: Optional[List[Player]] = None, max_players=2):
if not players:
players = self.players_ready[:max_players]
self.games.append(Game(players, manager=self))
game = Game(players, manager=self)
self.games.append(game)
for p in players:
self.metadata[p.name].ready = False
print(f"Game started : {' vs '.join([p.name for p in players])}")
await game.new_game()
def reset(self):
players = len(self.players)
......@@ -72,27 +91,27 @@ class LobbyManager(ClientManager):
self.send(p, MessageToPlayer.Reset)
self.sio.disconnect(m.sid)
self.lobby.clear()
self.players.clear()
self.metadata.clear()
self.games.clear()
print(f"Reset done, {players} players, {games} games.")
return msg
def send(self, to: Player, message: MessageToPlayer, extra=None):
data = {message: message.name}
if extra:
data["extra"] = extra
self.sio.send(message)
pass
async def send(self, to: Player, message: MessageToPlayer, extras=None):
sid = self.metadata[to.name].sid
data = {"message": str(message.name)}
if extras:
data["extra"] = extras
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
extras = {"players": [p.name for p in self.players]}
print(f"Lobby| Received message from {sid}: {data}.")
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:
if option.value in data:
......@@ -100,34 +119,44 @@ class LobbyManager(ClientManager):
if option == MessageFromPlayer.Waiting:
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:
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]
message = MessageToPlayer.ReadyToStart \
if len(self.players_ready) > 1 else MessageToPlayer.Waiting
else:
print(f"Still alone ready!")
message = MessageToPlayer.ReadyToStart
extras["playersReady"] = [p.name for p in self.players_ready]
elif option == MessageFromPlayer.Bet:
# FIXME vraie annonce, pas juste carre d'as lol
self.announces(player=sender,
announce=Announce(bet=CARRE_ACE))
game: Game = self.game_with(sender)
# TODO: connect with current game, return appropriate message
announce = Announce(bet=CARRE_ACE)
self.just_announced(player=sender,
announce=announce)
print(f"Lobby| Player {sender.name} just announced {announce}.")
extras["youBet"] = announce.bet
elif option == MessageFromPlayer.Menteur:
self.announces(player=sender, announce=Announce())
# TODO: connect with current game, return appropriate message
self.just_announced(player=sender, announce=Announce())
extras["youBet"] = False
body = {"message": message.name if message else "none"}
if extras:
body["extras"] = extras
return json.dumps(body)
if message:
game = asyncio.create_task(self.maybe_start_game())
await self.send(sender, message, extras)
await game
def which_player(self, sid) -> Player:
sender: Optional[Player] = None
......@@ -139,8 +168,8 @@ class LobbyManager(ClientManager):
def game_with(self, player: Player) -> Game:
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)
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]:
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):
self.send(p, message)
@abstractmethod
def send(self,
async def send(self,
to: Player,
message: MessageToPlayer,
extra=None):
......
......@@ -25,7 +25,7 @@ class Game:
self.current_bet: Optional[Hand] = None
self.manager = manager
def message(self, message: MessageToPlayer,
async def message(self, message: MessageToPlayer,
*to: Player,
extra=None
) -> None:
......@@ -33,7 +33,7 @@ class Game:
if not to:
to = self.players
for player in to:
self.manager.send(player, message, extra)
await self.manager.send(player, message, extra)
@property
def global_hand(self) -> Hand:
......@@ -41,6 +41,7 @@ class Game:
return Hand(cards=all_cards)
async def new_game(self):
print(f"Game starting with {self.players}!")
self.deck.reset()
while len(self.players) > 1:
......@@ -48,14 +49,14 @@ class Game:
if self.defeats[loser] == 5:
print(f"{loser} is eliminated!")
self.message(MessageToPlayer.Lose, loser)
await self.message(MessageToPlayer.Lose, loser)
self.players.remove(loser)
else:
print(f"{loser} lost the round, now playing with {self.defeats[loser] + 1} cards!")
winner = self.players[0]
self.message(MessageToPlayer.Win, winner)
self.message(MessageToPlayer.WinnerIs, extra=winner)
await self.message(MessageToPlayer.Win, winner)
await self.message(MessageToPlayer.WinnerIs, extra=winner)
print(f"Game over - {winner.name} wins with {len(winner.hand)} cards!")
async def new_turn(self) -> Player:
......@@ -67,7 +68,7 @@ class Game:
# Distribution
self.deck.reset()
self.message(MessageToPlayer.WaitTurn)
await self.message(MessageToPlayer.WaitTurn)
for current_player in self.players:
current_player.clear()
count_player_cards = self.defeats[current_player] + 1
......@@ -77,7 +78,7 @@ class Game:
current_player.give(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.")
# Tour
......@@ -88,7 +89,7 @@ class Game:
if loser is not None:
self.players.remove(loser)
self.players.insert(0, loser)
self.message(MessageToPlayer.LoseRound, extra=loser.name)
await self.message(MessageToPlayer.LoseRound, extra=loser.name)
return loser
last_player = current_player
......@@ -142,14 +143,14 @@ class Game:
print(f"| {current_player}'s turn >")
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
# FIXME: Wait for player announce? Maybe just sleep 10?
announce = await current_player.announce(self.current_bet)
if announce.bet:
self.current_bet = announce.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:
print(f"You cannot say Menteur on first round, {current_player}!")
......@@ -160,7 +161,7 @@ class Game:
print("CARRE D'AS!")
announce = Announce() # MENTEUR obligatoire
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)
if announce.bet:
......
......@@ -3,8 +3,7 @@ from typing import Optional
import socketio
from server.game.lobby import LobbyManager
from server.game.message import MessageToPlayer
from server.game.lobby import LobbyManager, Metadata
from server.model.hand import Hand
from server.model.players import Player, Announce
......@@ -23,34 +22,38 @@ class ClientPlayer(Player):
self.ready = False
async def announce(self, current_bet: Optional[Hand]) -> Announce:
announce = None
while not self.lobby.metadata[self.name].fresh_announce:
lobby.send_waiting_for(self)
metadata: Metadata = self.lobby.metadata[self.name]
print(f"Asking Client {self.name} for announce...", end="")
while not metadata.last_announce and metadata.fresh_announce:
await lobby.send_waiting_for(self)
print(".", end="")
sleep(2)
return lobby.last_announces[self]
print(f" {metadata.last_announce.bet}!")
return metadata.last_announce
@sio.event
async def connect(sid, environ):
print("[WS] Connect ", sid, environ)
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)
@sio.event
async def message(sid, 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")
async def ping_server(sid, data):
print("[WS] Ping received:", data)
await sio.emit('messageChannel', "PONG")
await sio.emit('messageChannel', "PONG", room=sid)
@sio.event
def 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