diff --git a/CHANGELOG.md b/CHANGELOG.md index d7a37054335076c7f0ec4282677e8e742da29cb3..fbce8a9795d9d6d58e37a19a876a1b5319985a15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,8 +13,22 @@ ### Added +- Send full websocket url in player_info. +- ">90"% code coverage in tests + ### Changed +- `extra_setup_functions` now only contain hook callback classes (`hook_callbacks`). Therefore, the `func` and `kwargs` + fields were + removed and the kwargs are now the standard values for defined hooks. This reduced the complexity of the config. +- The study config can now overwrite environment config attributes. This reduces the need to copy environment configs + for each level in the config. +- Most time comparisons (countdowns, etc.) are now compared with `<=` and not `<`. This is handy for testing and + definition. +- Player config in the environment class is now a dataclass and not a dict. The content remains the same. Just the + access changes from dict access to normal object like access. +- Some type hint additions + ### Deprecated ### Removed diff --git a/cooperative_cuisine/configs/environment_config.yaml b/cooperative_cuisine/configs/environment_config.yaml index e63620d0843c21a7f77e0dbf92538a5acc0c1779..e9188198069ad26875177645f39bcf8d39f1838d 100644 --- a/cooperative_cuisine/configs/environment_config.yaml +++ b/cooperative_cuisine/configs/environment_config.yaml @@ -183,6 +183,7 @@ hook_callbacks: - progress_started - progress_finished - content_ready + - dispenser_item_returned callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder '' callback_class_kwargs: diff --git a/cooperative_cuisine/configs/human_readable_print_templates.yaml b/cooperative_cuisine/configs/human_readable_print_templates.yaml index b190f6bccf1f0a3a3c580a8e37dd4c5f05e56365..cb9c47e9d634a2a320ec0456858e58a444e021fb 100644 --- a/cooperative_cuisine/configs/human_readable_print_templates.yaml +++ b/cooperative_cuisine/configs/human_readable_print_templates.yaml @@ -25,3 +25,4 @@ on_item_transition: "$item became $result." progress_started: "Item $item started progressing." progress_finished: "Item $item finished its progress." content_ready: "Meal $result was created on $before." +dispenser_item_returned: "Player $player returned $item to $counter." \ No newline at end of file diff --git a/cooperative_cuisine/counters.py b/cooperative_cuisine/counters.py index cd84be94e982e3c6e49ecefd501dbe075be84237..bf97c26b5886f738d122c282e8aa57cbcfe3d113 100644 --- a/cooperative_cuisine/counters.py +++ b/cooperative_cuisine/counters.py @@ -68,6 +68,7 @@ from cooperative_cuisine.hooks import ( PRE_PLATE_DISPENSER_DROP_OFF, PRE_PLATE_DISPENSER_PICK_UP, POST_PLATE_DISPENSER_PICK_UP, + DISPENSER_ITEM_RETURNED, ) from cooperative_cuisine.state_representation import CounterState @@ -511,6 +512,7 @@ class Dispenser(Counter): return return_this def drop_off(self, item: Item, player: str = "0") -> Item | None: + self.hook(DISPENSER_ITEM_RETURNED, player=player, counter=self, item=item) if self.occupied_by.can_combine(item): return self.occupied_by.combine(item) diff --git a/cooperative_cuisine/game_server.py b/cooperative_cuisine/game_server.py index 28a4d6f62c63613eb04f6efbd5115a4d4728cf23..2e4dbe9f0dae8a0354fcd9b676b12a6bca7dac46 100644 --- a/cooperative_cuisine/game_server.py +++ b/cooperative_cuisine/game_server.py @@ -142,6 +142,11 @@ class EnvironmentHandler: self.client_ids_to_player_hashes = {} """A dictionary mapping client IDs to player hashes.""" self.allowed_manager: list[str] = [] + """List of manager ids that are allowed to manage/create environments.""" + self.host: str = "" + """The host string (e.g., localhost) of the game server.""" + self.port: int = 8000 + """The port of the game server.""" def create_env( self, environment_config: CreateEnvironmentConfig @@ -225,6 +230,7 @@ class EnvironmentHandler: "client_id": client_id, "player_hash": player_hash, "player_id": player_id, + "websocket_url": f"ws://{self.host}:{self.port}/ws/player/{client_id}", } def add_player(self, config: AdditionalPlayer) -> dict[str, PlayerInfo]: @@ -560,6 +566,10 @@ class EnvironmentHandler: def extend_allowed_manager(self, manager: list[str]): self.allowed_manager.extend(manager) + def set_host_and_port(self, host, port): + self.host = host + self.port = port + class PlayerConnectionManager: """ @@ -819,6 +829,7 @@ def main( loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) environment_handler.extend_allowed_manager(manager_ids) + environment_handler.set_host_and_port(host=host, port=port) loop.create_task(environment_handler.environment_steps()) config = uvicorn.Config(app, host=host, port=port, loop=loop) server = uvicorn.Server(config) diff --git a/cooperative_cuisine/hooks.py b/cooperative_cuisine/hooks.py index f16b10afe108fd2572ba801a01d0dca679882e21..c541562b25e7018c8442e3a0b562af5b8ae40b99 100644 --- a/cooperative_cuisine/hooks.py +++ b/cooperative_cuisine/hooks.py @@ -77,6 +77,8 @@ POST_PLATE_DISPENSER_PICK_UP = "post_plate_dispenser_pick_up" PRE_PLATE_DISPENSER_DROP_OFF = "pre_plate_dispenser_drop_off" POST_PLATE_DISPENSER_DROP_OFF = "post_plate_dispenser_drop_off" +DISPENSER_ITEM_RETURNED = "dispenser_item_returned" + CUTTING_BOARD_PROGRESS = "cutting_board_progress" CUTTING_BOARD_100 = "cutting_board_100" diff --git a/cooperative_cuisine/pygame_2d_vis/drawing.py b/cooperative_cuisine/pygame_2d_vis/drawing.py index 2e0ef10a4a884ed1e0bb2156a023d29442f9d8b9..1207752c1c6c246c4574f0049435337c37dfe81f 100644 --- a/cooperative_cuisine/pygame_2d_vis/drawing.py +++ b/cooperative_cuisine/pygame_2d_vis/drawing.py @@ -14,7 +14,7 @@ from scipy.spatial import KDTree from cooperative_cuisine import ROOT_DIR from cooperative_cuisine.environment import Environment -from cooperative_cuisine.pygame_2d_vis.game_colors import colors +from cooperative_cuisine.pygame_2d_vis.game_colors import colors, RGB from cooperative_cuisine.state_representation import ( PlayerState, CookingEquipmentState, @@ -22,10 +22,6 @@ from cooperative_cuisine.state_representation import ( EffectState, ) -USE_PLAYER_COOK_SPRITES = True -SHOW_INTERACTION_RANGE = False -SHOW_COUNTER_CENTERS = False - def calc_angle(vec_a: list[float], vec_b: list[float]) -> float: a = pygame.math.Vector2(vec_a) @@ -86,6 +82,22 @@ class Visualizer: self.fire_time_steps = 8 self.observation_screen = None + self.USE_PLAYER_COOK_SPRITES = ( + config["Gui"]["use_player_cook_sprites"] + if "Gui" in config and "use_player_cook_sprites" in config["Gui"] + else True + ) + self.SHOW_INTERACTION_RANGE = ( + config["Gui"]["show_interaction_range"] + if "Gui" in config and "show_interaction_range" in config["Gui"] + else False + ) + self.SHOW_COUNTER_CENTERS = ( + config["Gui"]["show_counter_centers"] + if "Gui" in config and "show_counter_centers" in config["Gui"] + else False + ) + def create_player_colors(self, n) -> None: """Create different colors for the players. The color hues are sampled uniformly in HSV-Space, then the corresponding colors from the defined colors list are looked up. @@ -308,6 +320,26 @@ class Visualizer: screen.blit(image, rect) + def draw_cook( + self, + screen: pygame.Surface, + grid_size: float, + pos: npt.NDArray[float] | list[float], + color: RGB, + facing: npt.NDArray[float] | list[float], + ): + pygame.draw.circle( + screen, + color, + pos - facing * grid_size * 0.25, + grid_size * 0.2, + ) + + img_path = self.config["Cook"]["parts"][0]["path"] + angle = calc_angle(facing.tolist(), [0, 1]) + size = self.config["Cook"]["parts"][0]["size"] * grid_size + self.draw_image(screen, img_path, size, pos, angle) + def draw_players( self, screen: pygame.Surface, @@ -329,19 +361,11 @@ class Visualizer: facing = np.array(player_dict["facing_direction"], dtype=float) - if USE_PLAYER_COOK_SPRITES: - pygame.draw.circle( - screen, - colors[self.player_colors[p_idx]], - pos - facing * grid_size * 0.25, - grid_size * 0.2, + if self.USE_PLAYER_COOK_SPRITES: + self.draw_cook( + screen, grid_size, pos, colors[self.player_colors[p_idx]], facing ) - img_path = self.config["Cook"]["parts"][0]["path"] - angle = calc_angle(facing.tolist(), [0, 1]) - size = self.config["Cook"]["parts"][0]["size"] * grid_size - self.draw_image(screen, img_path, size, pos, angle) - else: player_radius = 0.4 size = player_radius * grid_size @@ -368,7 +392,7 @@ class Visualizer: ), ) - if SHOW_INTERACTION_RANGE: + if self.SHOW_INTERACTION_RANGE: pygame.draw.circle( screen, colors["blue"], @@ -753,7 +777,7 @@ class Visualizer: item=effect, ) - if SHOW_COUNTER_CENTERS: + if self.SHOW_COUNTER_CENTERS: pos = np.array(counter["pos"]) * grid_size pygame.draw.circle(screen, colors["green1"], pos, 3) pygame.draw.circle(screen, colors["green1"], pos, 3) diff --git a/cooperative_cuisine/pygame_2d_vis/gui.py b/cooperative_cuisine/pygame_2d_vis/gui.py index 02ea6b3cbc40320306c901a73904944900501151..c2d6be8f4f8ed944bc9868a2597b1bbb9260e396 100644 --- a/cooperative_cuisine/pygame_2d_vis/gui.py +++ b/cooperative_cuisine/pygame_2d_vis/gui.py @@ -153,7 +153,6 @@ class PyGameGUI: self.key_sets: list[PlayerKeySet] = [] - self.websocket_url = f"ws://{game_host}:{game_port}/ws/player/" self.websockets = {} if CONNECT_WITH_STUDY_SERVER: @@ -212,9 +211,10 @@ class PyGameGUI: self.sub_processes = [] - self.layout_file_paths = sorted( - (ROOT_DIR / "configs" / "layouts").rglob("*.layout") - ) + self.layout_file_paths_dict = { + p.name: p for p in (ROOT_DIR / "configs" / "layouts").rglob("*.layout") + } + self.layout_file_paths = sorted(list(self.layout_file_paths_dict.keys())) self.current_layout_idx = 0 self.last_state: StateRepresentation @@ -540,7 +540,23 @@ class PyGameGUI: ) # self.press_a_image.set_dimensions(new_dims) - + if not self.CONNECT_WITH_STUDY_SERVER: + assert len(self.layout_file_paths) != 0, "No layout files." + dropdown_width, dropdown_height = 200, 40 + self.layout_selection = pygame_gui.elements.UIDropDownMenu( + relative_rect=pygame.Rect( + ( + 0, + 0, + ), + (dropdown_width, dropdown_height), + ), + manager=self.manager, + options_list=self.layout_file_paths, + starting_option="basic.layout" + if "basic.layout" in self.layout_file_paths + else random.choice(self.layout_file_paths), + ) player_selection_rect = pygame.Rect( (0, 0), ( @@ -1017,6 +1033,11 @@ class PyGameGUI: self.fullscreen_button, ] + if not self.CONNECT_WITH_STUDY_SERVER: + self.start_screen_elements.append(self.layout_selection) + else: + self.other_elements.append(self.layout_selection) + self.tutorial_screen_elements = [ self.tutorial_image, self.continue_button, @@ -1168,8 +1189,8 @@ class PyGameGUI: served_meals = state["served_meals"] - row_height = self.window_height * 0.04 - container_width = self.scroll_width_completed_meals * 0.9 + row_height = self.window_height * 0.07 + container_width = self.scroll_width_completed_meals container_height = len(served_meals) * row_height main_container = pygame_gui.elements.UIPanel( @@ -1195,34 +1216,89 @@ class PyGameGUI: "top_target": last_completed_meals[idx - 1], } - container = pygame_gui.elements.UIPanel( - relative_rect=pygame.Rect( - (0, 0), - ( - container_width, - row_height, - ), + rect = pygame.Rect( + (0, 0), + ( + container_width / 2, + row_height, ), + ) + container = pygame_gui.elements.UIPanel( + relative_rect=rect, object_id="#graph_container", manager=self.manager, container=main_container, anchors=anchors, ) - meal = re.sub(r"(?<!^)(?=[A-Z])", " ", meal) - meal = meal.replace("(", "").replace(")", "") - text = f"Player {player} served a {meal}." + text = ":" + rect = pygame.Rect( + (0, 0), + (container_width / 10, row_height), + ) + rect.left = 0 meal_label = pygame_gui.elements.UILabel( text=text, - relative_rect=pygame.Rect( - (0, 0), - (container_width, row_height), - ), + relative_rect=rect, manager=self.manager, container=container, - object_id="#recipe", + object_id="#served_meal", anchors={"center": "center"}, ) + + cook_surface = pygame.Surface( + (row_height, row_height), flags=pygame.SRCALPHA + ) + player_idx = int(player) + player_color = colors[self.vis.player_colors[player_idx]] + self.vis.draw_cook( + screen=cook_surface, + grid_size=row_height, + pos=np.array([row_height / 2, row_height / 2]), + color=player_color, + facing=np.array([0, 1]), + ) + rect = cook_surface.get_rect() + rect.right = 0 + cook_image = pygame_gui.elements.UIImage( + relative_rect=rect, + image_surface=cook_surface, + manager=self.manager, + container=container, + anchors={ + "centery": "centery", + "right": "right", + "right_target": meal_label, + }, + ) + + meal_surface = pygame.Surface( + (row_height, row_height), flags=pygame.SRCALPHA + ) + self.vis.draw_item( + pos=np.array([row_height / 2, row_height / 2]), + item={"type": "Plate"}, + plate=True, + screen=meal_surface, + grid_size=row_height, + ) + self.vis.draw_item( + pos=np.array([row_height / 2, row_height / 2]), + item={"type": meal}, + plate=True, + screen=meal_surface, + grid_size=row_height, + ) + rect = meal_surface.get_rect() + # rect.left = 0 + meal_image = pygame_gui.elements.UIImage( + relative_rect=rect, + image_surface=meal_surface, + manager=self.manager, + container=container, + anchors={"centery": "centery", "left_target": meal_label}, + ) + last_completed_meals.append(container) self.scroll_space_completed_meals.set_scrollable_area_dimensions( @@ -1347,7 +1423,10 @@ class PyGameGUI: environment_config_path = ROOT_DIR / "configs" / "tutorial_env_config.yaml" else: environment_config_path = ROOT_DIR / "configs" / "environment_config.yaml" - layout_path = self.layout_file_paths[self.current_layout_idx] + layout_path = self.layout_file_paths_dict[ + self.layout_selection.selected_option + ] + # layout_path = self.layout_file_paths[self.current_layout_idx] item_info_path = ROOT_DIR / "configs" / "item_info.yaml" with open(item_info_path, "r") as file: @@ -1398,6 +1477,8 @@ class PyGameGUI: number_key_sets=min(self.number_humans_to_be_added, num_key_set), disjunct=self.split_players, ) + self.level_info = env_info + self.level_info["name"] = self.layout_selection.selected_option def update_pregame_screen(self): self.level_name_label.set_text( @@ -1536,10 +1617,7 @@ class PyGameGUI: else: log.warning("COULD NOT GET GAME CONNECTION") self.menu_state = MenuStates.Start - - self.number_players = ( - self.number_humans_to_be_added + self.number_bots_to_be_added - ) + self.number_players = -1 if self.split_players: assert ( @@ -1556,7 +1634,7 @@ class PyGameGUI: def create_and_connect_bot(self, player_id, player_info): player_hash = player_info["player_hash"] print( - f'--general_plus="agent_websocket:{self.websocket_url + player_info["client_id"]};player_hash:{player_hash};agent_id:{player_id}"' + f'--general_plus="agent_websocket:{player_info["websocket_url"]};player_hash:{player_hash};agent_id:{player_id}"' ) if self.USE_AAAMBOS_AGENT: sub = Popen( @@ -1569,7 +1647,7 @@ class PyGameGUI: str(ROOT_DIR / "configs" / "agents" / "arch_config.yml"), "--run_config", str(ROOT_DIR / "configs" / "agents" / "run_config.yml"), - f'--general_plus="agent_websocket:{self.websocket_url + player_info["client_id"]};player_hash:{player_hash};agent_id:{player_id}"', + f'--general_plus="agent_websocket:{player_info["websocket_url"]};player_hash:{player_hash};agent_id:{player_id}"', f"--instance={player_hash}", ] ), @@ -1581,7 +1659,7 @@ class PyGameGUI: [ "python", str(ROOT_DIR / "configs" / "agents" / "random_agent.py"), - f'--uri {self.websocket_url + player_info["client_id"]}', + f'--uri {player_info["websocket_url"]}', f"--player_hash {player_hash}", f"--player_id {player_id}", ] @@ -1594,7 +1672,7 @@ class PyGameGUI: for p, (player_id, player_info) in enumerate(self.player_info.items()): if p < self.number_humans_to_be_added: # add player websockets - websocket = connect(self.websocket_url + player_info["client_id"]) + websocket = connect(player_info["websocket_url"]) message_dict = { "type": PlayerRequestType.READY.value, "player_hash": player_info["player_hash"], @@ -1618,7 +1696,7 @@ class PyGameGUI: state = self.request_state() - self.vis.create_player_colors(len(state["players"])) + self.vis.create_player_colors(self.level_info["number_players"]) self.kitchen_width = state["kitchen"]["width"] self.kitchen_height = state["kitchen"]["height"] @@ -1806,12 +1884,14 @@ class PyGameGUI: if not self.last_level: self.get_game_connection() else: - self.current_layout_idx += 1 - self.create_env_on_game_server() - if self.current_layout_idx == len(self.layout_file_paths) - 1: - self.last_level = True - else: - log.debug(f"LEVEL: {self.layout_file_paths[self.current_layout_idx]}") + # self.current_layout_idx += 1 + self.menu_state = MenuStates.Start + return + # self.create_env_on_game_server(tutorial=False) + # if self.current_layout_idx == len(self.layout_file_paths) - 1: + # self.last_level = True + # else: + # log.debug(f"LEVEL: {self.layout_file_paths[self.current_layout_idx]}") self.menu_state = MenuStates.PreGame diff --git a/cooperative_cuisine/pygame_2d_vis/sample_state.json b/cooperative_cuisine/pygame_2d_vis/sample_state.json index 8d89362d6b345051b09cadadfc7dd72fa5898bb7..9dc284656177119c435c06f38db9f99c7e7ad7a5 100644 --- a/cooperative_cuisine/pygame_2d_vis/sample_state.json +++ b/cooperative_cuisine/pygame_2d_vis/sample_state.json @@ -3,21 +3,31 @@ { "id": "0", "pos": [ - 3.0, - 4.0 + 7.909655140524512, + 3.0028150498882398 ], "facing_direction": [ - 0, - 1 + -1.0, + 0.0 + ], + "holding": { + "id": "aacee793b279497b8d0acae3cce5f3ed", + "category": "Item", + "type": "Extinguisher", + "progress_percentage": 0.0, + "inverse_progress": false, + "active_effects": [] + }, + "current_nearest_counter_pos": [ + 7.0, + 4.0 ], - "holding": null, - "current_nearest_counter_pos": null, - "current_nearest_counter_id": null + "current_nearest_counter_id": "cca086918f474776a14905e126860b1b" } ], "counters": [ { - "id": "819fdb02a7fb4c42b45ffa5be4e4a475", + "id": "948e6a547c974d96b90e576fc5e5be51", "category": "Counter", "type": "Counter", "pos": [ @@ -32,9 +42,9 @@ "active_effects": [] }, { - "id": "2a9bc5a9a2a8404686ba4ce7be7b7ded", + "id": "5e89ff31afb743269c8a679b5a87f831", "category": "Counter", - "type": "Stove", + "type": "Counter", "pos": [ 1.0, 0.0 @@ -43,22 +53,13 @@ 0, 1 ], - "occupied_by": { - "id": "ba22928384814741bb1b40a8e9d90e20", - "category": "ItemCookingEquipment", - "type": "Pan", - "progress_percentage": 0.0, - "inverse_progress": false, - "active_effects": [], - "content_list": [], - "content_ready": null - }, + "occupied_by": null, "active_effects": [] }, { - "id": "76fed17b6b8e44f8b5058ef1c8b7e985", + "id": "133ec6053e474f71b0f1efcdb1b8b074", "category": "Counter", - "type": "Stove", + "type": "Sink", "pos": [ 2.0, 0.0 @@ -67,39 +68,177 @@ 0, 1 ], + "occupied_by": [], + "active_effects": [] + }, + { + "id": "69a0bbf53ccd41299f4a6e5dd832c91f", + "category": "Counter", + "type": "SinkAddon", + "pos": [ + 3.0, + 0.0 + ], + "orientation": [ + 0, + 1 + ], + "occupied_by": [], + "active_effects": [] + }, + { + "id": "a3fff164260f40e78a56cbe9e0efc29e", + "category": "Counter", + "type": "Counter", + "pos": [ + 4.0, + 0.0 + ], + "orientation": [ + 0, + 1 + ], + "occupied_by": null, + "active_effects": [] + }, + { + "id": "02f968e55566408298b7e287a074e771", + "category": "Counter", + "type": "Counter", + "pos": [ + 5.0, + 0.0 + ], + "orientation": [ + 0, + 1 + ], + "occupied_by": null, + "active_effects": [] + }, + { + "id": "86f8121622b64242b74a3da5275ee9c0", + "category": "Counter", + "type": "Counter", + "pos": [ + 6.0, + 0.0 + ], + "orientation": [ + 0, + 1 + ], + "occupied_by": null, + "active_effects": [] + }, + { + "id": "4656b49e7def41e4a9763dc99907c4d3", + "category": "Counter", + "type": "Counter", + "pos": [ + 7.0, + 0.0 + ], + "orientation": [ + 0, + 1 + ], + "occupied_by": null, + "active_effects": [ + { + "id": "4aacd988b0a349fa8bb51c2c641f2b03", + "type": "Fire", + "progress_percentage": 0.0, + "inverse_progress": true + } + ] + }, + { + "id": "cfaefb59f3da48abacfe5da895f8c69f", + "category": "Counter", + "type": "Stove", + "pos": [ + 8.0, + 0.0 + ], + "orientation": [ + 0, + 1 + ], "occupied_by": { - "id": "018b874741e74b6e886ae3d618ab4c5b", + "id": "68cfe6148402435e8ae628453eaf4182", "category": "ItemCookingEquipment", - "type": "Pot", + "type": "Pan", "progress_percentage": 0.0, "inverse_progress": false, - "active_effects": [], - "content_list": [], + "active_effects": [ + { + "id": "2946c19cb5c54d728e2c2e446ff0b7a2", + "type": "Fire", + "progress_percentage": 0.0, + "inverse_progress": true + } + ], + "content_list": [ + { + "id": "bdc75eeb4e204f838eb9c4d4d430b7a4", + "category": "Item", + "type": "BurntCookedPatty", + "progress_percentage": 0.0, + "inverse_progress": false, + "active_effects": [] + } + ], "content_ready": null }, "active_effects": [] }, { - "id": "fc11c7d9139149c0841772e61237bb36", + "id": "e5c84475e12d4f5ca0858b9b0170b7b5", "category": "Counter", - "type": "Counter", + "type": "Stove", "pos": [ - 3.0, + 9.0, 0.0 ], "orientation": [ 0, 1 ], - "occupied_by": null, + "occupied_by": { + "id": "c714f4bd045542679442fc09676ff0e5", + "category": "ItemCookingEquipment", + "type": "Pan", + "progress_percentage": 0.2979377, + "inverse_progress": true, + "active_effects": [ + { + "id": "ab608721b5ce4ae9ae0850ff94f7c233", + "type": "Fire", + "progress_percentage": 0.0, + "inverse_progress": true + } + ], + "content_list": [ + { + "id": "207410ced44c48afa4c5376d3275457e", + "category": "Item", + "type": "BurntCookedPatty", + "progress_percentage": 0.0, + "inverse_progress": false, + "active_effects": [] + } + ], + "content_ready": null + }, "active_effects": [] }, { - "id": "c368566316be499199798a66e6e67936", + "id": "d9f7c7cd40d84d138bf612237dacd052", "category": "Counter", - "type": "DeepFryer", + "type": "Stove", "pos": [ - 4.0, + 10.0, 0.0 ], "orientation": [ @@ -107,9 +246,9 @@ 1 ], "occupied_by": { - "id": "0499b155f3d14a5ab29c250694781437", + "id": "b4dc7034fd9346139113bebc540d2934", "category": "ItemCookingEquipment", - "type": "Basket", + "type": "Pan", "progress_percentage": 0.0, "inverse_progress": false, "active_effects": [], @@ -119,11 +258,11 @@ "active_effects": [] }, { - "id": "30e99d656950442693120b071d362df7", + "id": "3109cb9cd95d44b7aa7121f68fd08b8b", "category": "Counter", - "type": "Oven", + "type": "Stove", "pos": [ - 5.0, + 11.0, 0.0 ], "orientation": [ @@ -131,9 +270,9 @@ 1 ], "occupied_by": { - "id": "7a53dc8c7ff74d4298e6194c22a4496f", + "id": "72e69260b0bd41728847a99eabdc21d0", "category": "ItemCookingEquipment", - "type": "Peel", + "type": "Pot", "progress_percentage": 0.0, "inverse_progress": false, "active_effects": [], @@ -143,11 +282,11 @@ "active_effects": [] }, { - "id": "68672d07face4654b341df651e2a9e18", + "id": "2100f2099a044c7f8ad73ce1df3a983f", "category": "Counter", "type": "Counter", "pos": [ - 6.0, + 12.0, 0.0 ], "orientation": [ @@ -158,19 +297,19 @@ "active_effects": [] }, { - "id": "5e164dbdefaa4b6ea2875a0fb2ee678a", + "id": "8f28489317504cf5821f66f3f7464faa", "category": "Counter", "type": "TomatoDispenser", "pos": [ - 7.0, - 0.0 + 0.0, + 1.0 ], "orientation": [ - 0, - 1 + 1, + 0 ], "occupied_by": { - "id": "e96572a3d637465182610e06e5568046", + "id": "7735241303a14377b81debe2259ee587", "category": "Item", "type": "Tomato", "progress_percentage": 0.0, @@ -180,21 +319,200 @@ "active_effects": [] }, { - "id": "79dfbbe5648b48bfaaca0795fa867b05", + "id": "03392ae38a8c47f989e824417c08acfb", "category": "Counter", - "type": "OnionDispenser", + "type": "Counter", "pos": [ - 8.0, - 0.0 + 5.0, + 1.0 + ], + "orientation": [ + -1, + 0 + ], + "occupied_by": null, + "active_effects": [] + }, + { + "id": "6320c7f17c134559a573416b451186ce", + "category": "Counter", + "type": "Counter", + "pos": [ + 6.0, + 1.0 + ], + "orientation": [ + -1, + 0 + ], + "occupied_by": null, + "active_effects": [] + }, + { + "id": "ae28bd2ab9944fd5a6b06aad5c363b39", + "category": "Counter", + "type": "Counter", + "pos": [ + 7.0, + 1.0 + ], + "orientation": [ + 1, + 0 + ], + "occupied_by": null, + "active_effects": [] + }, + { + "id": "d3c651aef12f47b9a3aa28e855967da3", + "category": "Counter", + "type": "Counter", + "pos": [ + 12.0, + 1.0 + ], + "orientation": [ + -1, + 0 + ], + "occupied_by": null, + "active_effects": [] + }, + { + "id": "e8e6e458654240cb91f1349b1cde822f", + "category": "Counter", + "type": "MeatDispenser", + "pos": [ + 0.0, + 2.0 + ], + "orientation": [ + 1, + 0 + ], + "occupied_by": { + "id": "11924ae300ba42168ba51408827a716f", + "category": "Item", + "type": "Meat", + "progress_percentage": 0.0, + "inverse_progress": false, + "active_effects": [] + }, + "active_effects": [] + }, + { + "id": "76a860efb20742afa65353be01e8216f", + "category": "Counter", + "type": "Counter", + "pos": [ + 5.0, + 2.0 + ], + "orientation": [ + -1, + 0 + ], + "occupied_by": null, + "active_effects": [] + }, + { + "id": "f6e6112b2c5147ecb7a7c579e312013c", + "category": "Counter", + "type": "Counter", + "pos": [ + 6.0, + 2.0 ], "orientation": [ 0, 1 ], + "occupied_by": null, + "active_effects": [] + }, + { + "id": "ef9321de91bc4f809bf97741c2d2427f", + "category": "Counter", + "type": "Counter", + "pos": [ + 7.0, + 2.0 + ], + "orientation": [ + 1, + 0 + ], + "occupied_by": null, + "active_effects": [] + }, + { + "id": "0d95336bff754e9d98d8432923f4e460", + "category": "Counter", + "type": "Counter", + "pos": [ + 12.0, + 2.0 + ], + "orientation": [ + -1, + 0 + ], + "occupied_by": null, + "active_effects": [] + }, + { + "id": "8caee0a79f554d90b47b019c473086f2", + "category": "Counter", + "type": "BunDispenser", + "pos": [ + 0.0, + 3.0 + ], + "orientation": [ + 1, + 0 + ], + "occupied_by": { + "id": "aa7875154ceb49819fe1bf4f5edde3d4", + "category": "Item", + "type": "Bun", + "progress_percentage": 0.0, + "inverse_progress": false, + "active_effects": [] + }, + "active_effects": [] + }, + { + "id": "a868e52120194ded8f003cdbc2185bc8", + "category": "Counter", + "type": "Counter", + "pos": [ + 12.0, + 3.0 + ], + "orientation": [ + -1, + 0 + ], + "occupied_by": null, + "active_effects": [] + }, + { + "id": "b594bc7368214b36944e0f932a3b1703", + "category": "Counter", + "type": "LettuceDispenser", + "pos": [ + 0.0, + 4.0 + ], + "orientation": [ + 1, + 0 + ], "occupied_by": { - "id": "6c1d352c4a7042eebf012fb6d8296546", + "id": "8aa47d225fab4298939980c8df4da209", "category": "Item", - "type": "Onion", + "type": "Lettuce", "progress_percentage": 0.0, "inverse_progress": false, "active_effects": [] @@ -202,152 +520,147 @@ "active_effects": [] }, { - "id": "e60972ae9cd141f7b2fe0d855726d348", + "id": "c8bee431c9fd43b89b69b5854967cf38", + "category": "Counter", + "type": "Counter", + "pos": [ + 5.0, + 4.0 + ], + "orientation": [ + -1, + 0 + ], + "occupied_by": null, + "active_effects": [] + }, + { + "id": "8b3aa0c1bd4442d29b63dad48ce25431", + "category": "Counter", + "type": "Counter", + "pos": [ + 6.0, + 4.0 + ], + "orientation": [ + 0, + -1 + ], + "occupied_by": null, + "active_effects": [] + }, + { + "id": "cca086918f474776a14905e126860b1b", "category": "Counter", - "type": "LettuceDispenser", + "type": "Counter", "pos": [ - 9.0, - 0.0 + 7.0, + 4.0 ], "orientation": [ 0, - 1 + -1 ], - "occupied_by": { - "id": "f8332245ea194cfa8483ec62eeb7eeae", - "category": "Item", - "type": "Lettuce", - "progress_percentage": 0.0, - "inverse_progress": false, - "active_effects": [] - }, + "occupied_by": null, "active_effects": [] }, { - "id": "31aaf4f559aa4d8788f9e78085f3f15e", + "id": "721d14790a5e40b2a32f2d003bc29d56", "category": "Counter", - "type": "BunDispenser", + "type": "ServingWindow", "pos": [ - 10.0, - 0.0 + 12.0, + 4.0 ], "orientation": [ - 0, - 1 + -1, + 0 ], - "occupied_by": { - "id": "0620c75ee8a54b8db0a08a793e7e06bd", - "category": "Item", - "type": "Bun", - "progress_percentage": 0.0, - "inverse_progress": false, - "active_effects": [] - }, + "occupied_by": null, "active_effects": [] }, { - "id": "c1696096776d4a10aa05c434fa9c51a9", + "id": "0aa0b19ec9c244ffbd9547a025ef8d1a", "category": "Counter", "type": "Counter", "pos": [ - 11.0, - 0.0 + 0.0, + 5.0 ], "orientation": [ - 0, - 1 + 1, + 0 ], "occupied_by": null, "active_effects": [] }, { - "id": "26fcb7e5da2540f682d112ab22ecd981", + "id": "41756b5af0dc474ebd3c006eb26ebaf2", "category": "Counter", "type": "Counter", "pos": [ - 0.0, - 1.0 + 5.0, + 5.0 ], "orientation": [ - 1, + -1, 0 ], "occupied_by": null, "active_effects": [] }, { - "id": "d75487f9fa8147df968f083c0d614043", + "id": "42b5088f9ac8465487d6c2a04b59e254", "category": "Counter", - "type": "MeatDispenser", + "type": "Counter", "pos": [ - 11.0, - 1.0 + 6.0, + 5.0 ], "orientation": [ -1, 0 ], - "occupied_by": { - "id": "895cf2010ee849848cf34ff75e8402af", - "category": "Item", - "type": "Meat", - "progress_percentage": 0.0, - "inverse_progress": false, - "active_effects": [] - }, + "occupied_by": null, "active_effects": [] }, { - "id": "59e4887fe9734b45b7a6b4d2eb26bfdf", + "id": "98d647ae303a4fc4ba11ec954e4d83f1", "category": "Counter", "type": "Counter", "pos": [ - 0.0, - 2.0 + 7.0, + 5.0 ], "orientation": [ 1, 0 ], - "occupied_by": { - "id": "c4a332c3ec224bb295d068c5941a9f75", - "category": "Item", - "type": "Extinguisher", - "progress_percentage": 0.0, - "inverse_progress": false, - "active_effects": [] - }, + "occupied_by": null, "active_effects": [] }, { - "id": "f822fbdaa8b947f6a373308098530955", + "id": "2ca419ec0556401bbc6f860ed144b904", "category": "Counter", - "type": "PotatoDispenser", + "type": "ServingWindow", "pos": [ - 11.0, - 2.0 + 12.0, + 5.0 ], "orientation": [ -1, 0 ], - "occupied_by": { - "id": "4729948a21504531a89abc2e58564a6a", - "category": "Item", - "type": "Potato", - "progress_percentage": 0.0, - "inverse_progress": false, - "active_effects": [] - }, + "occupied_by": null, "active_effects": [] }, { - "id": "3a768b2b149848979694e83b7ddf9ae3", + "id": "9cf2c6b5724b40ec8cab1354f3c0c6a8", "category": "Counter", - "type": "ServingWindow", + "type": "Counter", "pos": [ 0.0, - 3.0 + 6.0 ], "orientation": [ 1, @@ -357,144 +670,116 @@ "active_effects": [] }, { - "id": "e722cd2a13cd45e6b8f410e1095972df", + "id": "8510852f420b44a3a3527e17dad8cec7", "category": "Counter", - "type": "FishDispenser", + "type": "Counter", "pos": [ - 11.0, - 3.0 + 5.0, + 6.0 ], "orientation": [ -1, 0 ], - "occupied_by": { - "id": "c9788eae65eb4cc1893a1a658725022b", - "category": "Item", - "type": "Fish", - "progress_percentage": 0.0, - "inverse_progress": false, - "active_effects": [] - }, + "occupied_by": null, "active_effects": [] }, { - "id": "079e5824edf74c91a206cef8c7e6a1cb", + "id": "1ce2c536c07b47b3b163b2057dacc48b", "category": "Counter", "type": "Counter", "pos": [ - 0.0, - 4.0 + 6.0, + 6.0 ], "orientation": [ - 1, + -1, 0 ], "occupied_by": null, "active_effects": [] }, { - "id": "c4e3620010784af4b952644831d9f8ed", + "id": "0cfdacbfbd354156b1f2ab004737a268", "category": "Counter", - "type": "DoughDispenser", + "type": "Counter", "pos": [ - 11.0, - 4.0 + 7.0, + 6.0 ], "orientation": [ - -1, + 1, 0 ], - "occupied_by": { - "id": "59c0f10dc74f4ecdb559f24acd812cc3", - "category": "Item", - "type": "Dough", - "progress_percentage": 0.0, - "inverse_progress": false, - "active_effects": [] - }, + "occupied_by": null, "active_effects": [] }, { - "id": "1182d2edae2f4756b8242ceabc7dddc0", + "id": "d723c46f4af0414c8c6d384f768389c1", "category": "Counter", - "type": "CuttingBoard", + "type": "PlateDispenser", "pos": [ - 0.0, - 5.0 + 12.0, + 6.0 ], "orientation": [ - 1, + -1, 0 ], - "occupied_by": null, + "occupied_by": [], "active_effects": [] }, { - "id": "90a3d17b698241368e02e56c90d387c4", + "id": "5e6f67c12aeb46079961a04f73933675", "category": "Counter", - "type": "CheeseDispenser", + "type": "Trashcan", "pos": [ - 11.0, - 5.0 + 0.0, + 7.0 ], "orientation": [ - -1, + 1, 0 ], - "occupied_by": { - "id": "0d3a459f08494e67b854aaaa04d44628", - "category": "Item", - "type": "Cheese", - "progress_percentage": 0.0, - "inverse_progress": false, - "active_effects": [] - }, + "occupied_by": null, "active_effects": [] }, { - "id": "0d73239968b943f4a545479af1e9d630", + "id": "2026e37f603d4e99aa82642ee006da01", "category": "Counter", "type": "Counter", "pos": [ - 0.0, - 6.0 + 5.0, + 7.0 ], "orientation": [ - 1, + -1, 0 ], "occupied_by": null, "active_effects": [] }, { - "id": "3d3c2611a2fb4f75a92e991bb0691efd", + "id": "8ecf87e04c074550a4d2278ee5cf40e9", "category": "Counter", - "type": "SausageDispenser", + "type": "Counter", "pos": [ - 11.0, - 6.0 + 6.0, + 7.0 ], "orientation": [ -1, 0 ], - "occupied_by": { - "id": "c8c7a7352d024049b730193f41ad243e", - "category": "Item", - "type": "Sausage", - "progress_percentage": 0.0, - "inverse_progress": false, - "active_effects": [] - }, + "occupied_by": null, "active_effects": [] }, { - "id": "2041cebba42c496abb362931926cff19", + "id": "278f258098c8452eb62af48b9d633c37", "category": "Counter", - "type": "CuttingBoard", + "type": "Counter", "pos": [ - 0.0, + 7.0, 7.0 ], "orientation": [ @@ -505,22 +790,31 @@ "active_effects": [] }, { - "id": "c8809b1e4f5349838c4bdbee4bc60cb3", + "id": "f36a734b4b8b414289a8aed484e3f71b", "category": "Counter", "type": "Counter", "pos": [ - 11.0, + 12.0, 7.0 ], "orientation": [ -1, 0 ], - "occupied_by": null, + "occupied_by": { + "id": "e7c6addcecd64129b07ad5da4129e3be", + "category": "ItemCookingEquipment", + "type": "Plate", + "progress_percentage": 0.0, + "inverse_progress": false, + "active_effects": [], + "content_list": [], + "content_ready": null + }, "active_effects": [] }, { - "id": "b6eb1077789749749564b6d139a907e7", + "id": "9d36bff22ff54a318b3c423406a4a518", "category": "Counter", "type": "Counter", "pos": [ @@ -535,7 +829,7 @@ "active_effects": [] }, { - "id": "5903eebafe47418fb2d908e4ef413895", + "id": "34ad760314064dc68afa6edde44e72a0", "category": "Counter", "type": "Counter", "pos": [ @@ -550,9 +844,9 @@ "active_effects": [] }, { - "id": "d94d02901d6d4afeb4f0dd685a383a90", + "id": "1ec90a2d503740d49e9c7533fff2580f", "category": "Counter", - "type": "PlateDispenser", + "type": "CuttingBoard", "pos": [ 2.0, 8.0 @@ -561,34 +855,13 @@ 0, -1 ], - "occupied_by": [ - { - "id": "2989438d9250431f96adfb9beecc1a64", - "category": "ItemCookingEquipment", - "type": "Plate", - "progress_percentage": 0.0, - "inverse_progress": false, - "active_effects": [], - "content_list": [], - "content_ready": null - }, - { - "id": "7a3c01e1a4304ec7afd5f23553c85efc", - "category": "ItemCookingEquipment", - "type": "Plate", - "progress_percentage": 0.0, - "inverse_progress": false, - "active_effects": [], - "content_list": [], - "content_ready": null - } - ], + "occupied_by": null, "active_effects": [] }, { - "id": "14e5cc8c37b4442db41fab14e8395ab6", + "id": "335848f26a324ecb8ccd2a0d15ed9376", "category": "Counter", - "type": "Sink", + "type": "Counter", "pos": [ 3.0, 8.0 @@ -597,13 +870,13 @@ 0, -1 ], - "occupied_by": [], + "occupied_by": null, "active_effects": [] }, { - "id": "e7b1daaf31894f4b9a061e34588fc796", + "id": "d9569e0fe3994f8fbbfc8170bc5c8cd3", "category": "Counter", - "type": "SinkAddon", + "type": "CuttingBoard", "pos": [ 4.0, 8.0 @@ -612,11 +885,11 @@ 0, -1 ], - "occupied_by": [], + "occupied_by": null, "active_effects": [] }, { - "id": "89e9cbc142bb43eeabd1f66c50fa070f", + "id": "3813a87c41ea4ab6a93f2fcbd78d2d7a", "category": "Counter", "type": "Counter", "pos": [ @@ -631,9 +904,9 @@ "active_effects": [] }, { - "id": "3d276d7435884de6b9cdd03fa8258b48", + "id": "784698c175c9422c88902605cf616b14", "category": "Counter", - "type": "Trashcan", + "type": "Counter", "pos": [ 6.0, 8.0 @@ -646,7 +919,7 @@ "active_effects": [] }, { - "id": "bcc17cc501d64224b84110a3a3d485a0", + "id": "e10cccc9d9de4d8f9d12b3bf195dcbf4", "category": "Counter", "type": "Counter", "pos": [ @@ -661,7 +934,7 @@ "active_effects": [] }, { - "id": "a3396bf4217a4cc5bca66fffeccdbcce", + "id": "e6631a6f8a0c457ea25743ab25a861b7", "category": "Counter", "type": "Counter", "pos": [ @@ -672,13 +945,22 @@ 0, -1 ], - "occupied_by": null, + "occupied_by": { + "id": "5ed8db414ff2455db3023c5cd2b7d6e9", + "category": "ItemCookingEquipment", + "type": "Plate", + "progress_percentage": 0.0, + "inverse_progress": false, + "active_effects": [], + "content_list": [], + "content_ready": null + }, "active_effects": [] }, { - "id": "ed59ba248e5d42dfbb5345fc8a9f951b", + "id": "4133e57be9244e9fa55999e0903468cb", "category": "Counter", - "type": "Sink", + "type": "Counter", "pos": [ 9.0, 8.0 @@ -687,13 +969,22 @@ 0, -1 ], - "occupied_by": [], + "occupied_by": { + "id": "e950596c5e984600beeb1d578e6985fb", + "category": "ItemCookingEquipment", + "type": "Plate", + "progress_percentage": 0.0, + "inverse_progress": false, + "active_effects": [], + "content_list": [], + "content_ready": null + }, "active_effects": [] }, { - "id": "5f85b094511c421b9456c7b99cbdca0f", + "id": "ec0fd1e8271b4da789bc6ddf093700df", "category": "Counter", - "type": "SinkAddon", + "type": "Counter", "pos": [ 10.0, 8.0 @@ -702,11 +993,20 @@ 0, -1 ], - "occupied_by": [], + "occupied_by": { + "id": "b29a87b6f7704942ac46a097af11a679", + "category": "ItemCookingEquipment", + "type": "Plate", + "progress_percentage": 0.0, + "inverse_progress": false, + "active_effects": [], + "content_list": [], + "content_ready": null + }, "active_effects": [] }, { - "id": "c746964d6e2b47b7b69b89974759c885", + "id": "b3a066bded454a3ab793313812907f2a", "category": "Counter", "type": "Counter", "pos": [ @@ -717,35 +1017,76 @@ 0, -1 ], + "occupied_by": { + "id": "69ac44ee46874f1ab3e68f19bd30d70e", + "category": "ItemCookingEquipment", + "type": "Plate", + "progress_percentage": 0.0, + "inverse_progress": false, + "active_effects": [], + "content_list": [ + { + "id": "6cd16f5282134674bfaa2af56980a526", + "category": "Item", + "type": "ChoppedLettuce", + "progress_percentage": 0.0, + "inverse_progress": false, + "active_effects": [] + } + ], + "content_ready": null + }, + "active_effects": [] + }, + { + "id": "37b0cdde445542b68cdc5ba0078354b1", + "category": "Counter", + "type": "Counter", + "pos": [ + 12.0, + 8.0 + ], + "orientation": [ + 0, + -1 + ], "occupied_by": null, "active_effects": [] } ], "kitchen": { - "width": 12.0, - "height": 9.0 + "width": 13, + "height": 9 }, - "score": 0.0, + "score": -20.0, "orders": [ { - "id": "803780e9583f4aa8a346ce344ad7f115", - "category": "Order", - "meal": "FriedFish", - "start_time": "2000-01-01T00:00:00", - "max_duration": 51.522081 - }, - { - "id": "cb18db2be449467db108ac6b7e6bf09e", + "id": "838850dfbc784180a19fe39c28b5116a", "category": "Order", - "meal": "Burger", - "start_time": "2000-01-01T00:00:00", - "max_duration": 42.046972 + "meal": "TomatoSoup", + "start_time": "2000-01-01T00:00:51.496903", + "max_duration": 52.89172 } ], "ended": false, - "env_time": "2000-01-01T00:00:00.290519", - "remaining_time": 299.709481, - "view_restriction": null, + "env_time": "2000-01-01T00:00:58.759073", + "remaining_time": 241.240927, + "view_restrictions": [ + { + "direction": [ + -1.0, + 0.0 + ], + "position": [ + 7.909655140524512, + 3.0028150498882398 + ], + "angle": 70, + "counter_mask": null, + "range": 4 + } + ], "served_meals": [], - "info_msg": [] -} + "info_msg": [], + "all_players_ready": true +} \ No newline at end of file diff --git a/cooperative_cuisine/pygame_2d_vis/visualization.yaml b/cooperative_cuisine/pygame_2d_vis/visualization.yaml index 4b209c76e9cd7b41909d3c9a38b5d7f9c84954bc..55caec68ae2664262d8dad7a86f9518268d31737 100644 --- a/cooperative_cuisine/pygame_2d_vis/visualization.yaml +++ b/cooperative_cuisine/pygame_2d_vis/visualization.yaml @@ -1,6 +1,9 @@ # colors: https://www.webucator.com/article/python-color-constants-module/ Gui: + use_player_cook_sprites: True + show_interaction_range: False + show_counter_centers: False language: "de" GameWindow: diff --git a/cooperative_cuisine/recording.py b/cooperative_cuisine/recording.py index a71cc0b3654b67f238798726e19c756a2f1f8111..2ed4f9ec8d8fc5c5ffea4059b8dc35f396790e7a 100644 --- a/cooperative_cuisine/recording.py +++ b/cooperative_cuisine/recording.py @@ -219,5 +219,5 @@ def print_recorded_events_human_readable(jsonl_path: Path): if __name__ == "__main__": - json_lines_path: Path = Path(sys.argv[0]) + json_lines_path: Path = Path(sys.argv[1]) print_recorded_events_human_readable(json_lines_path) diff --git a/cooperative_cuisine/server_results.py b/cooperative_cuisine/server_results.py index 1134c8fc4c08a60426ac8857855385655be46ad6..a5b85aca0abb344583a8fade1674430703d06568 100644 --- a/cooperative_cuisine/server_results.py +++ b/cooperative_cuisine/server_results.py @@ -18,6 +18,8 @@ class PlayerInfo(TypedDict): """Hash of the player, for validation.""" player_id: str """ID of the player.""" + websocket_url: str + """The url for the websocket to connect to.""" class CreateEnvResult(TypedDict): diff --git a/cooperative_cuisine/study_server.py b/cooperative_cuisine/study_server.py index 501cfa4e99c66585bb1478c7cb36bf619ea50c3c..f26963fa62ba1bd53aa5453099e07521e4d1334c 100644 --- a/cooperative_cuisine/study_server.py +++ b/cooperative_cuisine/study_server.py @@ -79,6 +79,8 @@ class LevelInfo(BaseModel): """If the level is the last in the study.""" recipe_graphs: list[dict] """Graph representations for the recipes in this level.""" + number_players: int + """Number of players in this level.""" class StudyConfig(BaseModel): @@ -305,6 +307,7 @@ class Study: name=current_level["name"], last_level=self.last_level, recipe_graphs=self.current_running_env["recipe_graphs"], + number_players=len(self.current_running_env["player_info"]), ) return player_info, level_info else: @@ -474,6 +477,7 @@ class StudyManager: name="Tutorial", last_level=False, recipe_graphs=tutorial_env["recipe_graphs"], + number_players=1, ) player_info = tutorial_env["player_info"] return player_info, level_info diff --git a/tests/test_pygame.py b/tests/test_pygame.py index 9df43e0813184f20a159001c91684f149bc17fbb..740601f4052972c069ec7fc26c7e832753489c2b 100644 --- a/tests/test_pygame.py +++ b/tests/test_pygame.py @@ -4,7 +4,12 @@ import os import yaml from cooperative_cuisine import ROOT_DIR -from cooperative_cuisine.pygame_2d_vis.drawing import calc_angle, Visualizer, main +from cooperative_cuisine.pygame_2d_vis.drawing import ( + calc_angle, + Visualizer, + main, + save_screenshot, +) from cooperative_cuisine.pygame_2d_vis.game_colors import RGB, WHITE, colors @@ -37,4 +42,18 @@ def test_visualizer(): with open(ROOT_DIR / "pygame_2d_vis" / "sample_state.json", "r") as file: state = json.load(file) image = vis.get_state_image(40, state) - assert image.shape == (480, 360, 3) + assert image.shape == (520, 360, 3) + + +def test_drawing_debug(): + with open(ROOT_DIR / "pygame_2d_vis" / "visualization.yaml", "r") as f: + viz_config = yaml.safe_load(f) + + viz_config["Gui"]["use_player_cook_sprites"] = False + viz_config["Gui"]["show_interaction_range"] = True + viz_config["Gui"]["show_counter_centers"] = True + + with open(ROOT_DIR / "pygame_2d_vis" / "sample_state.json", "r") as f: + state = json.load(f) + save_screenshot(state, viz_config, ROOT_DIR / "generated" / "screenshot_2.jpg") + assert os.path.exists(os.path.join(ROOT_DIR, "generated", "screenshot_2.jpg")) diff --git a/tests/test_study_server.py b/tests/test_study_server.py index 20776e60b190ee93d4bceec0c89e38c35deb531e..a7996af049076542288800133eb5945b6c40a4c2 100644 --- a/tests/test_study_server.py +++ b/tests/test_study_server.py @@ -20,6 +20,7 @@ def test_valid_post_requests(): "player_id": "0", "client_id": "ksjdhfkjsdfn", "player_hash": "shdfbmsndfb", + "websocket_url": "jhvfshfvbsdnmf", } }, "env_id": "123456789", @@ -48,6 +49,7 @@ def test_valid_post_requests(): "player_id": "0", "client_id": "ksjdhfkjsdfn", "player_hash": "shdfbmsndfb", + "websocket_url": "jhvfshfvbsdnmf", } } @@ -103,6 +105,7 @@ def test_tutorial(): "player_id": "0", "client_id": "ksjdhfkjsdfn", "player_hash": "shdfbmsndfb", + "websocket_url": "jhvfshfvbsdnmf", } }, "env_id": "123456789",