diff --git a/overcooked_simulator/counters.py b/overcooked_simulator/counters.py index dfe0b24ed1bc4ff842b4932e4d8c790c697ad67e..9ae5405596c1d93f9bbec103c3d2de25eece964e 100644 --- a/overcooked_simulator/counters.py +++ b/overcooked_simulator/counters.py @@ -1,5 +1,6 @@ from __future__ import annotations +import logging from typing import TYPE_CHECKING, Optional if TYPE_CHECKING: @@ -15,6 +16,8 @@ from overcooked_simulator.game_items import ( Meal, ) +log = logging.getLogger(__name__) + class Counter: """Simple class for a counter at a specified position (center of counter). Can hold things on top.""" @@ -118,7 +121,7 @@ class ServingWindow(Counter): def drop_off(self, item) -> Item | None: reward = 5 - print(item) + log.debug(f"Drop off {item}") # TODO define rewards self.game_score.increment_score(reward) return None diff --git a/overcooked_simulator/main.py b/overcooked_simulator/main.py index 8dbd792ca7f4c2d2575b0eb0f58c1b9436076046..239779f471d534e3e9e4cb186735b01c24630226 100644 --- a/overcooked_simulator/main.py +++ b/overcooked_simulator/main.py @@ -1,4 +1,8 @@ +import logging +import os import sys +import threading +from datetime import datetime import pygame @@ -6,6 +10,24 @@ from overcooked_simulator import ROOT_DIR from overcooked_simulator.pygame_gui.pygame_gui import PyGameGUI from overcooked_simulator.simulation_runner import Simulator +log = logging.getLogger(__name__) + + +def setup_logging(): + path_logs = ROOT_DIR.parent / "logs" + os.makedirs(path_logs, exist_ok=True) + logging.basicConfig( + level=logging.DEBUG, + format="%(asctime)s %(levelname)-8s %(name)-50s %(message)s", + handlers=[ + logging.FileHandler( + path_logs / f"{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}_debug.log", + encoding="utf-8", + ), + logging.StreamHandler(sys.stdout), + ], + ) + def main(): simulator = Simulator( @@ -38,4 +60,13 @@ def main(): if __name__ == "__main__": - main() + setup_logging() + try: + main() + except Exception as e: + log.exception(e) + for thread in threading.enumerate(): + if isinstance(thread, Simulator): + thread.stop() + thread.join() + sys.exit(1) diff --git a/overcooked_simulator/overcooked_environment.py b/overcooked_simulator/overcooked_environment.py index ff5be6b8e66621d2e33f3d9631548b23d7f96b6f..599b35d411082aff10444576665fd54b1cacde4f 100644 --- a/overcooked_simulator/overcooked_environment.py +++ b/overcooked_simulator/overcooked_environment.py @@ -1,5 +1,6 @@ from __future__ import annotations +import logging import random from pathlib import Path @@ -20,6 +21,8 @@ from overcooked_simulator.game_items import ItemInfo # if TYPE_CHECKING: from overcooked_simulator.player import Player +log = logging.getLogger(__name__) + class GameScore: def __init__(self): @@ -27,7 +30,7 @@ class GameScore: def increment_score(self, score: int): self.score += score - print(self.score) + log.debug(f"Score: {self.score}") def read_score(self): return self.score @@ -356,7 +359,7 @@ class Environment: return distance < (player.radius * self.counter_side_length) def add_player(self, player_name: str, pos: npt.NDArray = None): - # print(f"Added player {player.name} to the game.") + log.debug(f"Add player {player_name} to the game") player = Player(player_name, self.counter_side_length, pos) self.players[player.name] = player if player.pos is None: @@ -369,7 +372,7 @@ class Environment: player.move_abs(self.free_positions[free_idx]) del self.free_positions[free_idx] else: - print("No free positions left in kitchens.") + log.debug("No free positions left in kitchens") def detect_collision_world_bounds(self, player: Player): """Checks for detections of the player and the world bounds. diff --git a/overcooked_simulator/player.py b/overcooked_simulator/player.py index 56313cd323b5cfeb94aa4cc5c07190657546c925..5e0fa68804c7513d1b6f081d89f9bec4cd47a806 100644 --- a/overcooked_simulator/player.py +++ b/overcooked_simulator/player.py @@ -1,3 +1,4 @@ +import logging from pathlib import Path from typing import Optional @@ -9,6 +10,8 @@ from overcooked_simulator import ROOT_DIR from overcooked_simulator.counters import Counter from overcooked_simulator.game_items import Item +log = logging.getLogger(__name__) + class Player: """Class representing a player in the game environment. A player consists of a name, their position and what @@ -108,7 +111,9 @@ class Player: returned_by_counter = counter.pick_up(on_hands=False) self.holding.combine(returned_by_counter) - print("Self:", self.holding, "Counter:", counter.occupied_by) + log.debug( + f"Self: {self.holding}, {counter.__class__.__name__}: {counter.occupied_by}" + ) def perform_interact_hold_start(self, counter: Counter): """Starts an interaction with the counter. Should be called for a diff --git a/overcooked_simulator/pygame_gui/pygame_gui.py b/overcooked_simulator/pygame_gui/pygame_gui.py index a9efc44a91cc0903604ee87403e62b21dc8d471a..24c42107ae6a1064552d08d9b7c0300553586c72 100644 --- a/overcooked_simulator/pygame_gui/pygame_gui.py +++ b/overcooked_simulator/pygame_gui/pygame_gui.py @@ -1,4 +1,5 @@ import colorsys +import logging import math import sys @@ -43,6 +44,9 @@ def create_polygon(n, length): return vecs +log = logging.getLogger(__name__) + + class PlayerKeySet: """Set of keyboard keys for controlling a player. First four keys are for movement. Order: Down, Up, Left, Right. @@ -406,6 +410,7 @@ class PyGameGUI: def start_pygame(self): """Starts pygame and the gui loop. Each frame the game state is visualized and keyboard inputs are read.""" + log.debug(f"Starting pygame gui at {self.FPS} fps") pygame.init() pygame.font.init() diff --git a/overcooked_simulator/simulation_runner.py b/overcooked_simulator/simulation_runner.py index 697ee553823d664f261c417b17f11c2bea76d028..4d38ac34ba0020837499f9c1c3bd5161d9717b93 100644 --- a/overcooked_simulator/simulation_runner.py +++ b/overcooked_simulator/simulation_runner.py @@ -1,9 +1,12 @@ +import logging import time from threading import Thread from overcooked_simulator import ROOT_DIR from overcooked_simulator.overcooked_environment import Environment, Action +log = logging.getLogger(__name__) + class Simulator(Thread): """Simulator main class which runs manages the environment and player inputs and game state outputs. @@ -103,5 +106,5 @@ class Simulator(Thread): def stop(self): """Stops the simulator""" - print("Stopping the simulation.") + log.debug("Stopping the simulation") self.finished = True