From cb98afa3d519fb2193302d0de625be597d64268e Mon Sep 17 00:00:00 2001
From: Dominik Battefeld <dbattefeld@techfak.uni-bielefeld.de>
Date: Tue, 19 Dec 2023 11:25:27 +0100
Subject: [PATCH] Add logging

---
 overcooked_simulator/counters.py              |  5 ++-
 overcooked_simulator/main.py                  | 33 ++++++++++++++++++-
 .../overcooked_environment.py                 |  9 +++--
 overcooked_simulator/player.py                |  7 +++-
 overcooked_simulator/pygame_gui/pygame_gui.py |  5 +++
 overcooked_simulator/simulation_runner.py     |  5 ++-
 6 files changed, 57 insertions(+), 7 deletions(-)

diff --git a/overcooked_simulator/counters.py b/overcooked_simulator/counters.py
index dfe0b24e..9ae54055 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 8dbd792c..239779f4 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 ff5be6b8..599b35d4 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 56313cd3..5e0fa688 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 a9efc44a..24c42107 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 697ee553..4d38ac34 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
-- 
GitLab