diff --git a/client/src/App.vue b/client/src/App.vue
index dbcd62a..68a66b3 100644
--- a/client/src/App.vue
+++ b/client/src/App.vue
@@ -1,7 +1,17 @@
-
+
+
+
+
+
+
@@ -11,9 +21,8 @@
import Vuex from 'vuex'
import 'es6-promise/auto' // Needed for Promise polyfill
import VueSocketIO from 'vue-socket.io'
- // import Game from "./components/Game";
import HelloWorld from "./components/HelloWorld";
- import ListenToSockets from "./Sockets";
+ import Sockets from "./Sockets";
Vue.use(Vuex);
@@ -54,7 +63,18 @@
name: "App",
components: {
HelloWorld,
- ListenToSockets
+ Sockets
+ },
+ data: function () {
+ return {
+ message: "WAITING"
+ }
+ },
+ methods: {
+ sendMessage: function(message) {
+ console.log("User wants to send", message);
+ this.$socket.emit("message", message);
+ }
}
};
@@ -69,4 +89,8 @@
color: #2c3e50;
margin-top: 60px;
}
+
+ #game {
+ margin-top: 20px;
+ }
diff --git a/client/src/Sockets.vue b/client/src/Sockets.vue
index 95e2d6c..676fbf3 100644
--- a/client/src/Sockets.vue
+++ b/client/src/Sockets.vue
@@ -44,10 +44,15 @@
pingServer() {
// Send the "pingServer" event to the server.
if (this.isConnected) {
- this.$socket.emit('pingServer', 'PING!');
+ this.sendMessage("Ping!");
console.log("Ping sent!");
}
},
+ sendMessage(message) {
+ this.$socket.emit('pingServer', message);
+ console.log("Message sent:", message);
+
+ },
logOn() {
this.$socket.onconnect();
},
diff --git a/client/src/components/Game.vue b/client/src/components/Game.vue
index 3e5cae6..b27d35b 100644
--- a/client/src/components/Game.vue
+++ b/client/src/components/Game.vue
@@ -2,6 +2,7 @@
Game on!
{{ msg }}
+ Count: {{ count }}
diff --git a/server/app.py b/server/app.py
index 966e34d..97d03ae 100644
--- a/server/app.py
+++ b/server/app.py
@@ -6,12 +6,12 @@ from fastapi.exceptions import RequestValidationError
from starlette.exceptions import HTTPException
from starlette.responses import PlainTextResponse
+from server.game.lobby import LobbyManager
from server.model.data import Game
# Game state
from server.model.players import RandomPlayer
from server.ws import sio
-game = Game()
# Server
app = FastAPI()
diff --git a/server/game/__init__.py b/server/game/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/server/game/__init__.py
diff --git a/server/game/lobby.py b/server/game/lobby.py
new file mode 100644
index 0000000..cde5843
--- /dev/null
+++ b/server/game/lobby.py
@@ -0,0 +1,52 @@
+from collections import defaultdict
+from typing import List, Dict
+
+from socketio import AsyncServer
+
+from server.game.manager import ClientManager
+from server.game.message import MessageToPlayer
+from server.model.data import Game
+from server.model.players import Player, Announce
+
+
+class LobbyManager(ClientManager):
+ """ A ClientManager that handles a lobby, then orchestrates games.
+ """
+
+ def __init__(self, sio: AsyncServer):
+ super().__init__()
+ self.last_announces: Dict[Player, Announce] = {}
+ self.lobby: Dict[Player, bool] = {}
+ self.games: List[Game] = []
+ self.sio = sio
+
+ @property
+ def nb_ready(self):
+ return len(self.players_ready)
+
+ @property
+ def players_ready(self):
+ return [k for k, v in self.lobby.items() if v]
+
+ async def add_player(self, player: Player, is_ready: bool = False) -> None:
+ self.lobby[player] = is_ready
+ print(f"Added {player} to a lobby with {len(self.lobby)} players.")
+ await self.sio.emit('messageChannel', "PONG")
+
+ def wants_to_play(self, player: Player):
+ self.lobby[player] = True
+ print(f"{player} ready to play! ({self.nb_ready} people ready)")
+
+ def announces(self, player: Player, announce: Announce):
+ self.last_announces[player] = announce
+ print(f"{player} ready to play! ({self.nb_ready} people ready)")
+
+ def start_game(self, max_players=2):
+ players = self.players_ready[:max_players]
+ self.games.append(Game(players, manager=self))
+
+ print(f"Game started : {' vs '.join([p.name for p in players])}")
+
+ def send(self, to: Player, message: MessageToPlayer, extra=None):
+ self.sio.send(message)
+ pass
diff --git a/server/game/manager.py b/server/game/manager.py
new file mode 100644
index 0000000..dff5c22
--- /dev/null
+++ b/server/game/manager.py
@@ -0,0 +1,22 @@
+from abc import ABC, abstractmethod
+from typing import List, Optional
+
+from server.game.message import MessageToPlayer
+from server.model.players import Player
+
+
+class ClientManager(ABC):
+ """
+ A listener of game state that notifies clients.
+ """
+ def __init__(self):
+ self.players: List[Player] = []
+
+ def notify(self, message: MessageToPlayer, only_for: Optional[Player] = None) -> None:
+ to = [only_for] if only_for else self.players
+ for p in to:
+ self.send(p, message)
+
+ @abstractmethod
+ def send(self, to: Player, message: MessageToPlayer, extra=None):
+ raise NotImplementedError("Send a message to clients ")
diff --git a/server/game/message.py b/server/game/message.py
new file mode 100644
index 0000000..544a263
--- /dev/null
+++ b/server/game/message.py
@@ -0,0 +1,17 @@
+from enum import Enum
+
+
+class MessageToPlayer(Enum):
+ Waiting = "WAITING_ROOM"
+ Ready = "READY_ROOM"
+ WaitTurn = "WAITING_TURN"
+ YourTurn = "YOUR_TURN"
+ Win = "WINNER"
+ Lose = "LOSER"
+
+
+class MessageFromPlayer(Enum):
+ Wating = "WAITING"
+ Ready = "READY"
+ Bet = "BET"
+ Menteur = "MENTEUR"
diff --git a/server/model/data.py b/server/model/data.py
index b19e9c3..8803794 100644
--- a/server/model/data.py
+++ b/server/model/data.py
@@ -2,6 +2,7 @@ import itertools
from collections import defaultdict
from typing import List, Dict, Optional
+from server.game.manager import ClientManager
from server.model.card import Card
from server.model.deck import Deck
from server.model.hand import Hand
@@ -9,7 +10,11 @@ from server.model.players import Player
class Game:
- def __init__(self, players=None, deck: Deck = Deck()):
+ def __init__(self,
+ players=None,
+ deck: Deck = Deck(),
+ manager: Optional[ClientManager] = None
+ ):
if players is None:
players = []
diff --git a/server/ws.py b/server/ws.py
index d284789..54643f1 100644
--- a/server/ws.py
+++ b/server/ws.py
@@ -1,21 +1,39 @@
+from typing import Optional
+
import socketio
+from server.game.lobby import LobbyManager
+from server.model.hand import Hand
+from server.model.players import Player, Announce
+
sio = socketio.AsyncServer(
async_mode='asgi',
logger=True,
cors_allowed_origins="*" # FIXME: CSRF Vulnerability
)
+lobby = LobbyManager(sio)
+
+
+class ClientPlayer(Player):
+ def __init__(self, lobby: LobbyManager):
+ super().__init__()
+ self.lobby = lobby
+
+ async def announce(self, current_bet: Optional[Hand]) -> Announce:
+ return lobby.last_announces[self]
@sio.event
-def connect(sid, environ):
+async def connect(sid, environ):
print("[WS] Connect ", sid, environ)
+ player = ClientPlayer(lobby)
+ await lobby.add_player(player)
@sio.event
-async def chat_message(sid, data):
+async def message(sid, data):
print("[WS] Message ", data)
- await sio.emit('reply', room=sid)
+ await sio.emit('messageChannel', "OK", room=sid)
@sio.on("pingServer")