Bläddra i källkod

Merge pull request #24 from NielsOverkamp/change-name

Change name
NielsOverkamp 5 år sedan
förälder
incheckning
0541bbf267
6 ändrade filer med 107 tillägg och 65 borttagningar
  1. 1 1
      frontend/keezen-frontend/src/StateRouter.js
  2. 9 6
      game.py
  3. 1 0
      option.py
  4. 3 0
      player.py
  5. 64 33
      ui/dog.html
  6. 29 25
      webserver.py

+ 1 - 1
frontend/keezen-frontend/src/StateRouter.js

@@ -48,7 +48,7 @@ export default function StateRouter() {
 
     console.log({path, path_code});
     const initial_state = path_code === null ?
-        { state: SiteState.WAITING_FOR_WS } :
+        { state: SiteState.START } :
         { state: SiteState.JOIN_LINK, game_code: path_code };
 
     const send = websocketStatus === WebsocketStatus.CONNECTED ?

+ 9 - 6
game.py

@@ -26,9 +26,10 @@ class Game(object):
 
     def join_player(self, name, color=None):
         if color is not None:
-            color_player = next((p for p in self.players if p.color == color and p.Name is None), None)
+            color_player = next((p for p in self.players if p.color == color and not p.connected), None)
             if color_player is not None:
                 color_player.name = name
+                color_player.connected = True
                 return color_player
 
         player = Player(None, name)
@@ -47,13 +48,15 @@ class Game(object):
             self.players.remove(player)
         else:
             player.name = None
+            player.connected = False
 
         self.set_pick_color_state()
 
-    def pick_color(self, player, color):
+    def pick_color(self, player, color, name):
+        player.name = name or player.name
         color_player = next((p for p in self.players if p.color == color), None)
-        if color_player is not None:
-            if color_player.name is None:
+        if color_player != player and color_player is not None:
+            if not color_player.connected:
                 # reconnect, merge
                 player.merge_from(color_player)
                 self.players.remove(color_player)
@@ -68,7 +71,7 @@ class Game(object):
 
 
     def set_pick_color_state(self):
-        used_colors = [player.color for player in self.players if player.color is not None and player.name is not None]
+        used_colors = [player.color for player in self.players if player.color is not None and player.connected]
         available_colors = [color for color in all_colors if color not in used_colors]
 
         for player in self.players:
@@ -190,7 +193,7 @@ class Game(object):
 
     def play_option(self, player, option):
         if option.code == OptionCode.PICK_COLOR:
-            return self.pick_color(player, option.color)
+            return self.pick_color(player, option.color, option.user_name)
         elif option.code == OptionCode.DEAL:
             return self.deal(player)
         elif option.code == OptionCode.SWAP_CARD:

+ 1 - 0
option.py

@@ -8,6 +8,7 @@ class OptionCode(str, Enum):
     NEW_GAME = "new_game"
     JOIN_GAME = "join_game"
     PICK_COLOR = "pick_color"
+    CHANGE_NAME = "change_name"
     DEAL = "deal"
     SWAP_CARD = "swap_card"
     PLAY_CARD = "play_card"

+ 3 - 0
player.py

@@ -19,6 +19,7 @@ class StateCode(str, Enum):
 
 
 class ErrorCode(str, Enum):
+    NO_GAME = "no_game"
     UNKNOWN_CODE = "unknown_code"
     COLOR_ALREADY_CHOSEN = "color_already_chosen"
     OPTION_NOT_ALLOWED = "option_not_allowed"
@@ -54,6 +55,7 @@ class Player(object):
     color: Color
     name: str
     game_code: int
+    connected: bool
     hand: List[Card]
     options: List[Option]
     message: str
@@ -70,6 +72,7 @@ class Player(object):
         self.color = color
         self.name = name
         self.game_code = None
+        self.connected = True
         self.hand = []
         self.options = []
         self.message = "Even wachten"

+ 64 - 33
ui/dog.html

@@ -3,7 +3,7 @@
     <head>
         <title>Dog</title>
         <style type="text/css">
-            body {
+            body, .input {
                 font-family: "Courier New", sans-serif;
                 text-align: center;
                 background-color: lightgray;
@@ -23,17 +23,24 @@
                 cursor: pointer;
                 user-select: none;
             }
-            .state, .name {
-                font-size: 1em;
-                padding: 1rem;
+            .state, .input {
+                font-size: 2em;
+                padding: 2rem;
             }
-            .name {
+            .input {
                 color: white;
-             }
+                line-height: 1;
+                padding: 1rem;
+                margin: 1rem;
+                border: thin solid;
+                min-height: 1em;
+                min-width: 1em;
+            }
         </style>
     </head>
     <body>
-        <div class="name" id="name">You</div>
+        <div><input type="number" class="input" id="gc" placeholder="1234" onchange="changeGameCode(this.value)"/></div>
+        <div><input type="text" class="input" id="name" placeholder="Jouw Naam" onchange="changeName(this.value)" /></div>
         <div class="state">
             <span class="message" id="msg">?</span>
         </div>
@@ -46,45 +53,69 @@
             <div class="button" id="b5" onclick="doOption(5)">6</div>
             <div class="button" id="b6" onclick="doOption(6)">7</div>
         </div>
+        <div id="json"/>
+
         <script>
-            var player = { options: [
-              {
-                code: 'newgame',
-                args: null,
-                text: 'Nieuw spel'
-                }, {
-                code: 'joingame',
-                args: { code: 3936 },
-                text: 'Doe mee met een spel'
-              }],
-              message: "Even wachten op de server"};
+            var player = {
+                options: [
+                    {
+                        code: 'new_game',
+                        text: 'Nieuw spel'
+                    }, {
+                        code: 'join_game',
+                        text: 'Doe mee met een spel'
+                    }],
+                message: "Even wachten op de server",
+                state: "start"
+            };
+            var json = "";
 
             function doOption(i) {
-              if (player.options.length > i) {
-                websocket.send(JSON.stringify(player.options[i]));
-              }
+                if (player.options.length > i) {
+                    const option = player.options[i];
+                    option.user_name = player.name;
+                    option.game_code = player.game_code;
+                    option.color = option.color || player.color;
+                    websocket.send(JSON.stringify(player.options[i]));
+                }
             }
 
             function show() {
-              var i;
-              for (i = 0; i < 7; i++) {
-                document.getElementById("b" + i.toString()).textContent = player.options.length > i ? player.options[i].text : '';
-              }
-              document.getElementById("msg").textContent = player.message;
-              var name = document.getElementById("name");
-              name.textContent = player.name ?? 'You';
-              if (player.color) {
-                name.style.color = player.color; 
-              }
+                var i;
+                for (i = 0; i < 7; i++) {
+                    document.getElementById("b" + i.toString()).textContent = player.options.length > i ? player.options[i].text : '';
+                }
+                document.getElementById("msg").textContent = player.message;
+                var name = document.getElementById("name");
+                if (player.color) {
+                    name.style.color = player.color;
+                }
+                const gc = document.getElementById("gc");
+                gc.value = player.game_code;
+                gc.disabled = player.state !== "start";
+                document.getElementById("json").textContent = json;
+            }
+
+            function changeName(name) {
+                player.name = name;
+                if (player.game_code) {
+                    const option = { code: "change_name", text: name, user_name: name }
+                    websocket.send(JSON.stringify(option));
+                }
             }
-            
+
+            function changeGameCode(code) {
+                player.game_code = code;
+            }
+
             websocket = new WebSocket("ws://127.0.0.1:6789/");
 
             websocket.onmessage = function (event) {
                 player = JSON.parse(event.data);
+                json = event.data;
                 show();
             }
-            
+
             show();
         </script>
     </body>

+ 29 - 25
webserver.py

@@ -79,27 +79,25 @@ async def notify(player_sockets):
     if player_sockets:
         await asyncio.wait([websocket.send(json.dumps(player, cls=DogEncoder)) for (player, websocket) in player_sockets])
 
-async def handler(websocket, path):
-    player = Player(name=users[0])
-    player.options = [
+async def notify_error(websocket, error_code, message, **kwargs):
+    reply = Player()
+    reply.message = message
+    reply.set_error(error_code, **kwargs)
+    reply.state = StateCode.START
+    reply.options = [
         Option(OptionCode.NEW_GAME, "Nieuw spel"), 
-        Option(OptionCode.JOIN_GAME, "Doe mee met een spel", game_code='3936')]
-    player.message = "Wat wil je doen?"
-    player.state = StateCode.START
+        Option(OptionCode.JOIN_GAME, "Doe mee met een spel")]
+    await notify([(reply, websocket)])
+
+
+async def handler(websocket, path):
+    player = None
     game_code = 0
     game = None
     try:
-        await notify([(player, websocket)])
-
         async for message in websocket:
             option = Option(**json.loads(message))
 
-            if not player.check_option(option):
-                await notify([(player, websocket)])
-                continue
-
-            player.set_error(None)
-
             if option.code == OptionCode.NEW_GAME:
                 game_code = random.randint(1000, 9999);
                 while game_code in games:
@@ -107,10 +105,6 @@ async def handler(websocket, path):
 
                 game = Game()
                 games[game_code] = game
-                if option.user_name is None:
-                    option.user_name = users[0]
-                    users.append(users[0])
-                    users.remove(users[0])
                 player = game.join_player(option.user_name)
                 player.game_code = game_code
                 sockets[game_code] = [(player, websocket)]
@@ -121,22 +115,32 @@ async def handler(websocket, path):
                 game = games.get(game_code) if game_code is not None and type(game_code) is int and game_code > 0 else None
 
                 if game is None:
-                    player.message = f"onbekande code {game_code}"
-                    player.set_error(ErrorCode.UNKNOWN_CODE, game_code=game_code)
-                    await notify([(player, websocket)])
+                    await notify_error(websocket, ErrorCode.UNKNOWN_CODE, f"onbekende code {game_code}", game_code=game_code)
                     continue
 
-                if option.user_name is None:
-                    option.user_name = users[0]
-                    users.append(users[0])
-                    users.remove(users[0])
                 player = game.join_player(option.user_name, option.color)
                 player.game_code = game_code
                 sockets[game_code].append((player, websocket))
                 await notify(sockets[game_code])
 
+            elif game is None or player is None:
+                await notify_error(websocket, ErrorCode.NO_GAME, f"Start eerst een nieuw spel of doe mee met een spel")
+
+            elif option.code == OptionCode.CHANGE_NAME:
+                player.name = option.user_name
+                for p in game.players:
+                    p.set_others(game.players)
+
+                await notify(sockets[game_code])
+
             else:
                 game = games[game_code]
+                player.set_error(None)
+
+                if not player.check_option(option):
+                    await notify([(player, websocket)])
+                    continue
+
                 game.play_option(player, option)
                 await notify(sockets[game_code])
     finally: