From d901dcf293b3fed7dd6855c2ff5e4ebf54631e08 Mon Sep 17 00:00:00 2001
From: fheinrich <fheinrich@techfak.uni-bielefeld.de>
Date: Wed, 13 Mar 2024 11:49:01 +0100
Subject: [PATCH] Changed player and bot number selection

- Looks simpler
- Adjusted button hiding on number of humans
- Kitchen size gets returned in level info
---
 cooperative_cuisine/game_server.py            |  6 +-
 cooperative_cuisine/pygame_2d_vis/gui.py      | 91 ++++++++++---------
 .../pygame_2d_vis/gui_theme.json              | 17 ++++
 .../locales/translations.de.json              |  4 +-
 .../locales/translations.en.json              |  6 +-
 .../pygame_2d_vis/visualization.yaml          |  2 +-
 cooperative_cuisine/server_results.py         |  2 +
 cooperative_cuisine/study_server.py           |  2 +
 tests/test_start.py                           |  7 +-
 9 files changed, 85 insertions(+), 52 deletions(-)

diff --git a/cooperative_cuisine/game_server.py b/cooperative_cuisine/game_server.py
index 2e4dbe9f..c017a1d0 100644
--- a/cooperative_cuisine/game_server.py
+++ b/cooperative_cuisine/game_server.py
@@ -190,9 +190,13 @@ class EnvironmentHandler:
         self.manager_envs[environment_config.manager_id].update([env_id])
 
         graphs = env.recipe_validation.get_recipe_graphs()
+        kitchen_size = (env.kitchen_width, env.kitchen_height)
 
         res = CreateEnvResult(
-            env_id=env_id, player_info=player_info, recipe_graphs=graphs
+            env_id=env_id,
+            player_info=player_info,
+            recipe_graphs=graphs,
+            kitchen_size=kitchen_size,
         )
         return res
 
diff --git a/cooperative_cuisine/pygame_2d_vis/gui.py b/cooperative_cuisine/pygame_2d_vis/gui.py
index c2d6be8f..bd31b535 100644
--- a/cooperative_cuisine/pygame_2d_vis/gui.py
+++ b/cooperative_cuisine/pygame_2d_vis/gui.py
@@ -220,7 +220,12 @@ class PyGameGUI:
         self.last_state: StateRepresentation
 
         self.player_info = {"0": {"name": "0"}}
-        self.level_info = {"name": "Level", "recipe_graphs": []}
+        self.level_info = {
+            "name": "Level",
+            "recipe_graphs": [],
+            "number_players": -1,
+            "kitchen_size": (0, 0),
+        }
         self.last_level = False
         self.beeped_once = False
         self.all_completed_meals = []
@@ -464,11 +469,6 @@ class PyGameGUI:
             )
         )
 
-    def get_translated_message(self, message: str) -> str:
-        # message: Message = self.fluent_bundle.get_message(message)
-        # text, errors = self.fluent_bundle.format_pattern(message.value)
-        return message
-
     def init_ui_elements(self):
         self.manager = pygame_gui.UIManager(
             (self.window_width, self.window_height),
@@ -592,31 +592,31 @@ class PyGameGUI:
             object_id="#split_players_button",
         )
 
-        players_container_rect = pygame.Rect(
+        rect = pygame.Rect(
             (0, 0),
             (
                 self.window_width * 0.6,
-                self.player_selection_container.get_abs_rect().height // 3,
+                self.player_selection_container.get_abs_rect().height * 0.35,
             ),
         )
         self.player_number_container = pygame_gui.elements.UIPanel(
-            relative_rect=players_container_rect,
+            relative_rect=rect,
             manager=self.manager,
             object_id="#players_players",
             container=self.player_selection_container,
             anchors={"top": "top", "centerx": "centerx"},
         )
 
-        bot_container_rect = pygame.Rect(
+        rect = pygame.Rect(
             (0, 0),
             (
                 self.window_width * 0.6,
-                self.player_selection_container.get_abs_rect().height // 3,
+                self.player_selection_container.get_abs_rect().height * 0.35,
             ),
         )
-        bot_container_rect.bottom = 0
+        rect.bottom = 0
         self.bot_number_container = pygame_gui.elements.UIPanel(
-            relative_rect=bot_container_rect,
+            relative_rect=rect,
             manager=self.manager,
             object_id="#players_bots",
             container=self.player_selection_container,
@@ -645,47 +645,53 @@ class PyGameGUI:
 
         size = 50
         add_player_button_rect = pygame.Rect((0, 0), (size, size))
-        add_player_button_rect.right = 0
         self.add_human_player_button = pygame_gui.elements.UIButton(
             relative_rect=add_player_button_rect,
             text="+",
             manager=self.manager,
             object_id="#quantity_button",
             container=self.player_number_container,
-            anchors={"right": "right", "centery": "centery"},
+            anchors={"left_target": self.added_bots_label, "centery": "centery"},
         )
 
         remove_player_button_rect = pygame.Rect((0, 0), (size, size))
-        remove_player_button_rect.left = 0
+        remove_player_button_rect.right = 0
         self.remove_human_button = pygame_gui.elements.UIButton(
             relative_rect=remove_player_button_rect,
             text="-",
             manager=self.manager,
             object_id="#quantity_button",
             container=self.player_number_container,
-            anchors={"left": "left", "centery": "centery"},
+            anchors={
+                "right": "right",
+                "right_target": self.added_bots_label,
+                "centery": "centery",
+            },
         )
 
         add_bot_button_rect = pygame.Rect((0, 0), (size, size))
-        add_bot_button_rect.right = 0
         self.add_bot_button = pygame_gui.elements.UIButton(
             relative_rect=add_bot_button_rect,
             text="+",
             manager=self.manager,
             object_id="#quantity_button",
             container=self.bot_number_container,
-            anchors={"right": "right", "centery": "centery"},
+            anchors={"left_target": self.added_bots_label, "centery": "centery"},
         )
 
         remove_bot_button_rect = pygame.Rect((0, 0), (size, size))
-        remove_bot_button_rect.left = 0
+        remove_bot_button_rect.right = 0
         self.remove_bot_button = pygame_gui.elements.UIButton(
             relative_rect=remove_bot_button_rect,
             text="-",
             manager=self.manager,
             object_id="#quantity_button",
             container=self.bot_number_container,
-            anchors={"left": "left", "centery": "centery"},
+            anchors={
+                "right": "right",
+                "right_target": self.added_bots_label,
+                "centery": "centery",
+            },
         )
 
         ########################################################################
@@ -867,7 +873,7 @@ class PyGameGUI:
 
         rect = pygame.Rect(
             (0, 0),
-            (self.window_width * 0.2, self.buttons_height),
+            (self.window_width * 0.3, self.buttons_height),
         )
         rect.bottomleft = (0, 0)
         self.score_label = pygame_gui.elements.UILabel(
@@ -1479,6 +1485,7 @@ class PyGameGUI:
             )
         self.level_info = env_info
         self.level_info["name"] = self.layout_selection.selected_option
+        self.level_info["number_players"] = num_players
 
     def update_pregame_screen(self):
         self.level_name_label.set_text(
@@ -1693,13 +1700,8 @@ class PyGameGUI:
 
     def setup_game(self):
         self.connect_websockets()
-
-        state = self.request_state()
-
         self.vis.create_player_colors(self.level_info["number_players"])
-
-        self.kitchen_width = state["kitchen"]["width"]
-        self.kitchen_height = state["kitchen"]["height"]
+        self.kitchen_width, self.kitchen_height = self.level_info["kitchen_size"]
 
     def stop_game_on_server(self, reason: str) -> None:
         log.debug(f"Stopping game: {reason}")
@@ -1747,18 +1749,28 @@ class PyGameGUI:
         )
         self.split_players = False
         self.multiple_keysets = False
-        self.player_minimum = 1
 
     def update_selection_elements(self):
-        if self.number_humans_to_be_added <= self.player_minimum:
+        if self.number_humans_to_be_added == 1:
             self.remove_human_button.disable()
-            self.number_humans_to_be_added = self.player_minimum
+            self.multiple_keysets_button.hide()
+            self.split_players_button.hide()
         else:
             self.remove_human_button.enable()
+            if self.number_humans_to_be_added < 2:
+                self.multiple_keysets_button.hide()
+            else:
+                self.multiple_keysets_button.show()
 
-        self.number_humans_to_be_added = max(
-            self.player_minimum, self.number_humans_to_be_added
-        )
+            if self.number_humans_to_be_added > 1 and self.multiple_keysets:
+                self.split_players_button.show()
+            else:
+                self.split_players_button.hide()
+
+        if self.number_bots_to_be_added == 0:
+            self.remove_bot_button.disable()
+        else:
+            self.remove_bot_button.enable()
 
         self.number_players = (
             self.number_humans_to_be_added + self.number_bots_to_be_added
@@ -1785,11 +1797,6 @@ class PyGameGUI:
         )
         self.split_players_button.set_text(text)
 
-        if self.multiple_keysets:
-            self.split_players_button.show()
-        else:
-            self.split_players_button.hide()
-
         if self.number_players == 0:
             self.start_button.disable()
         else:
@@ -1937,7 +1944,7 @@ class PyGameGUI:
 
                     case self.remove_human_button:
                         self.number_humans_to_be_added = max(
-                            self.player_minimum, self.number_humans_to_be_added - 1
+                            0, self.number_humans_to_be_added - 1
                         )
                     case self.remove_bot_button:
                         self.number_bots_to_be_added = max(
@@ -1948,10 +1955,6 @@ class PyGameGUI:
                         self.split_players = False
                     case self.split_players_button:
                         self.split_players = not self.split_players
-                        if self.split_players:
-                            self.player_minimum = 2
-                        else:
-                            self.player_minimum = 0
 
             ############################################
 
diff --git a/cooperative_cuisine/pygame_2d_vis/gui_theme.json b/cooperative_cuisine/pygame_2d_vis/gui_theme.json
index be4c5ad6..a6775335 100644
--- a/cooperative_cuisine/pygame_2d_vis/gui_theme.json
+++ b/cooperative_cuisine/pygame_2d_vis/gui_theme.json
@@ -97,16 +97,33 @@
     "colours": {
       "dark_bg": "#fffacd",
       "normal_border": "#fffacd"
+    },
+    "misc": {
+      "shape": "rounded_rectangle",
+      "border_width": "0",
+      "shadow_width": "0"
     }
   },
   "#players_players": {
     "colours": {
       "dark_bg": "#fffacd"
+    },
+    "misc": {
+      "shape": "rounded_rectangle",
+      "shape_corner_radius": "0",
+      "border_width": "0",
+      "shadow_width": "0"
     }
   },
   "#players_bots": {
     "colours": {
       "dark_bg": "#fffacd"
+    },
+    "misc": {
+      "shape": "rounded_rectangle",
+      "shape_corner_radius": "0",
+      "border_width": "0",
+      "shadow_width": "0"
     }
   },
   "#number_players_label": {
diff --git a/cooperative_cuisine/pygame_2d_vis/locales/translations.de.json b/cooperative_cuisine/pygame_2d_vis/locales/translations.de.json
index c51961e8..f792c21f 100644
--- a/cooperative_cuisine/pygame_2d_vis/locales/translations.de.json
+++ b/cooperative_cuisine/pygame_2d_vis/locales/translations.de.json
@@ -3,8 +3,8 @@
     "fullscreen": "Vollbild",
     "quit_game": "Beenden",
     "start_game": "Start",
-    "humans_to_be_added": "Menschliche Spieler: %{number}",
-    "bot_to_be_added": "Autonome Spieler: %{number}",
+    "humans_to_be_added": "Steuerbare Köche: %{number}",
+    "bots_to_be_added": "Bots: %{number}",
     "1_player": "1 Spieler",
     "2_players": "2 Spieler",
     "split_players_yes": "Köche aufteilen: Ja",
diff --git a/cooperative_cuisine/pygame_2d_vis/locales/translations.en.json b/cooperative_cuisine/pygame_2d_vis/locales/translations.en.json
index 2e96d104..5aae6e45 100644
--- a/cooperative_cuisine/pygame_2d_vis/locales/translations.en.json
+++ b/cooperative_cuisine/pygame_2d_vis/locales/translations.en.json
@@ -2,9 +2,9 @@
   "en": {
     "fullscreen": "Fullscreen",
     "quit_game": "Quit Game",
-    "start_game": "Start Game",
-    "humans_to_be_added": "Humans to be added: %{number}",
-    "bot_to_be_added": "Bot to be added: %{number}",
+    "start_game": "Start",
+    "humans_to_be_added": "Controllable cooks: %{number}",
+    "bots_to_be_added": "Bot to be added: %{number}",
     "1_player": "1 Player",
     "2_players": "2 Players",
     "split_players_yes": "Split cooks: Yes",
diff --git a/cooperative_cuisine/pygame_2d_vis/visualization.yaml b/cooperative_cuisine/pygame_2d_vis/visualization.yaml
index 55caec68..954ff07d 100644
--- a/cooperative_cuisine/pygame_2d_vis/visualization.yaml
+++ b/cooperative_cuisine/pygame_2d_vis/visualization.yaml
@@ -1,10 +1,10 @@
 # colors: https://www.webucator.com/article/python-color-constants-module/
 
 Gui:
+  language: "en"
   use_player_cook_sprites: True
   show_interaction_range: False
   show_counter_centers: False
-  language: "de"
 
 GameWindow:
   screen_margin: 100
diff --git a/cooperative_cuisine/server_results.py b/cooperative_cuisine/server_results.py
index a5b85aca..fd367bc9 100644
--- a/cooperative_cuisine/server_results.py
+++ b/cooperative_cuisine/server_results.py
@@ -31,6 +31,8 @@ class CreateEnvResult(TypedDict):
     """Information about the players."""
     recipe_graphs: list[dict]
     """Graph representation of the recipes possible in this env."""
+    kitchen_size: tuple[float, float]
+    """Size of the kitchen layout of this env."""
 
 
 class PlayerRequestResult(TypedDict):
diff --git a/cooperative_cuisine/study_server.py b/cooperative_cuisine/study_server.py
index f26963fa..c9ece46a 100644
--- a/cooperative_cuisine/study_server.py
+++ b/cooperative_cuisine/study_server.py
@@ -81,6 +81,8 @@ class LevelInfo(BaseModel):
     """Graph representations for the recipes in this level."""
     number_players: int
     """Number of players in this level."""
+    kitchen_size: tuple[float, float]
+    """Size of the created env of this level."""
 
 
 class StudyConfig(BaseModel):
diff --git a/tests/test_start.py b/tests/test_start.py
index 78470953..4bb89d7d 100644
--- a/tests/test_start.py
+++ b/tests/test_start.py
@@ -319,7 +319,12 @@ def test_json_schema():
 
 def test_server_result_definition():
     plater_info = PlayerInfo(client_id="123", player_hash="234567890", player_id="0")
-    CreateEnvResult(env_id="123344", player_info={"0": plater_info}, recipe_graphs=[])
+    CreateEnvResult(
+        env_id="123344",
+        player_info={"0": plater_info},
+        recipe_graphs=[],
+        kitchen_size=(0, 0),
+    )
     PlayerRequestResult(
         request_type=PlayerRequestType.READY,
         status=200,
-- 
GitLab