diff --git a/CHANGELOG.md b/CHANGELOG.md
index be5fec5110d6163960ab3084db4c75139aea53bf..ec679566d9e8b19dafd0afbada2f84c0a4999689 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -23,6 +23,9 @@
 - Level layouts from 2d-grid-overcooked-literature
 - Caching of graph recipe layouts
 - Score label changes color when score changes
+- Scoring optionally dependent on remaining times of orders
+- Score of order is shown in game
+- Possible max score is shown next to recipe graphs
 - Control screenshot, replay, single game/study server, gui via cli (sub commands)
 
 ### Changed
diff --git a/cooperative_cuisine/configs/environment_config.yaml b/cooperative_cuisine/configs/environment_config.yaml
index 25514c3bd6627f35df634e5836e9e617abc47f34..e11bb2dfc6726d4d4b2a87654f1cc88b4a9c4f1d 100644
--- a/cooperative_cuisine/configs/environment_config.yaml
+++ b/cooperative_cuisine/configs/environment_config.yaml
@@ -86,7 +86,7 @@ orders:
 
 player_config:
   radius: 0.4
-  speed_units_per_seconds: 6
+  speed_units_per_seconds: 5
   interaction_range: 1.25
   restricted_view: False
   view_angle: 70
@@ -106,13 +106,12 @@ hook_callbacks:
     hooks: [ completed_order ]
     callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
     callback_class_kwargs:
-      static_score: 20
+      time_dependence_func: !!python/name:cooperative_cuisine.scores.constant_score ''
+      time_dependence_kwargs: { }
+      static_score: 100
       score_on_specific_kwarg: meal_name
-      score_map:
-        Burger: 15
-        OnionSoup: 10
-        Salad: 5
-        TomatoSoup: 10
+      score_map: { }
+
   not_ordered_meals:
     hooks: [ serve_not_ordered_meal ]
     callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
diff --git a/cooperative_cuisine/configs/item_info.yaml b/cooperative_cuisine/configs/item_info.yaml
index f8a14b7f57adbe184f318892a2d236338c66b43e..5bfe9904a9f4461060a5803730645cdbc77bd98c 100644
--- a/cooperative_cuisine/configs/item_info.yaml
+++ b/cooperative_cuisine/configs/item_info.yaml
@@ -174,7 +174,7 @@ FishAndChips:
 
 BurgerWithChips:
   type: Meal
-  needs: [ Burger, Chips ]
+  needs: [ Bun, ChoppedLettuce, ChoppedTomato, CookedPatty, Chips ]
   equipment: ~
 
 Pizza:
diff --git a/cooperative_cuisine/configs/item_info_debug.yaml b/cooperative_cuisine/configs/item_info_debug.yaml
index f7783818b44059e9a004f627c60b433b6ac2e01a..ff43f34667f48a9cc981abb30eea923a789b1fcf 100644
--- a/cooperative_cuisine/configs/item_info_debug.yaml
+++ b/cooperative_cuisine/configs/item_info_debug.yaml
@@ -150,6 +150,11 @@ Burger:
   needs: [ Bun, ChoppedLettuce, ChoppedTomato, CookedPatty ]
   equipment: ~
 
+BurgerWithChips:
+  type: Meal
+  needs: [ Bun, ChoppedLettuce, ChoppedTomato, CookedPatty, Chips ]
+  equipment: ~
+
 Salad:
   type: Meal
   needs: [ ChoppedLettuce, ChoppedTomato ]
diff --git a/cooperative_cuisine/configs/layouts/study_layouts/1-4-bottleneck.layout b/cooperative_cuisine/configs/layouts/study_layouts/1-4-bottleneck.layout
index 60eb7af88bc47cc657b5d23e51556cad9a204fc0..a66163dadb89139302f67d35e1cea1fc1c3a53a9 100644
--- a/cooperative_cuisine/configs/layouts/study_layouts/1-4-bottleneck.layout
+++ b/cooperative_cuisine/configs/layouts/study_layouts/1-4-bottleneck.layout
@@ -1,12 +1,12 @@
-=#S+#====C#C#=
-T____#==#____|
-M_A__####__A_#
-B____________#
-L____####____$
-#____#==#____$
-#____#==#____P
-X____#==#____#
-=QQ#U====#@@@=
+=#S+#===C#C#=
+T____#=#____|
+M_A__###__A_#
+B___________#
+L____###____$
+#____#=#____$
+#____#=#____P
+X____#=#____#
+=QQ#U===#@@@=
 
 ; seconds=240
 ; plates={c:0, d:0}
diff --git a/cooperative_cuisine/configs/study/study_config.yaml b/cooperative_cuisine/configs/study/study_config.yaml
index e21045a79df9db46299d3da217f95e09b29adeca..d491af8801982c1acb218c46c6b8483aaad2610e 100644
--- a/cooperative_cuisine/configs/study/study_config.yaml
+++ b/cooperative_cuisine/configs/study/study_config.yaml
@@ -6,16 +6,15 @@ levels:
     name: "Level 1"
     seed: 12345
     config_overwrite:
-      player_config:
-        speed_units_per_seconds: 5
       game:
         time_limit_seconds: 300
-        validate_recipes: false
+        validate_recipes: true
       plates:
         clean_plates: 0
         dirty_plates: 0
         return_dirty: true
       orders:
+        serving_not_ordered_meals: false
         meals:
           all: false
           list:
@@ -29,8 +28,22 @@ levels:
           sample_on_dur_random_func:
             func: uniform
             kwargs:
-              a: 45
-              b: 35
+              a: 20
+              b: 30
+
+      hook_callbacks:
+        orders:
+          hooks: [ completed_order ]
+          callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
+          callback_class_kwargs:
+            time_dependence_func: !!python/name:cooperative_cuisine.scores.stepped_score ''
+            time_dependence_kwargs:
+              score_ratios: [ 0.5, 1, 1 ]
+              steps: [ 0, 0.25, 0.66 ]
+              round_decimals: 0
+            static_score: 20
+            score_on_specific_kwarg: meal_name
+            score_map: [ ]
 
   - config_path: CONFIGS_DIR/environment_config.yaml
     layout_path: LAYOUTS_DIR/study_layouts/1-4-bottleneck.layout
@@ -38,8 +51,6 @@ levels:
     name: "Level 2"
     seed: 12345
     config_overwrite:
-      player_config:
-        speed_units_per_seconds: 5
       game:
         time_limit_seconds: 300
       plates:
@@ -47,6 +58,7 @@ levels:
         dirty_plates: 0
         return_dirty: true
       orders:
+        serving_not_ordered_meals: false
         meals:
           all: false
           list:
@@ -61,8 +73,24 @@ levels:
           sample_on_dur_random_func:
             func: uniform
             kwargs:
-              a: 45
-              b: 35
+              a: 20
+              b: 30
+      hook_callbacks:
+        orders:
+          hooks: [ completed_order ]
+          callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
+          callback_class_kwargs:
+            time_dependence_func: !!python/name:cooperative_cuisine.scores.stepped_score ''
+            time_dependence_kwargs:
+              score_ratios: [ 0.5, 1, 1 ]
+              steps: [ 0, 0.25, 0.66 ]
+              round_decimals: 0
+            static_score: 20
+            score_on_specific_kwarg: meal_name
+            score_map:
+              Burger: 40
+              Salad: 20
+              TomatoSoup: 35
 
   - config_path: CONFIGS_DIR/environment_config.yaml
     layout_path: LAYOUTS_DIR/study_layouts/1-5-circle.layout
@@ -70,8 +98,6 @@ levels:
     name: "Level 3"
     seed: 12345
     config_overwrite:
-      player_config:
-        speed_units_per_seconds: 5
       game:
         time_limit_seconds: 300
         validate_recipes: true
@@ -80,6 +106,7 @@ levels:
         dirty_plates: 0
         return_dirty: true
       orders:
+        serving_not_ordered_meals: false
         meals:
           all: false
           list:
@@ -93,9 +120,21 @@ levels:
           sample_on_dur_random_func:
             func: uniform
             kwargs:
-              a: 45
-              b: 35
-
+              a: 20
+              b: 30
+      hook_callbacks:
+        orders:
+          hooks: [ completed_order ]
+          callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
+          callback_class_kwargs:
+            time_dependence_func: !!python/name:cooperative_cuisine.scores.stepped_score ''
+            time_dependence_kwargs:
+              score_ratios: [ 0.5, 1, 1 ]
+              steps: [ 0, 0.25, 0.66 ]
+              round_decimals: 0
+            static_score: 20
+            score_on_specific_kwarg: meal_name
+            score_map: [ ]
 
   - config_path: CONFIGS_DIR/environment_config.yaml
     layout_path: LAYOUTS_DIR/study_layouts/forced-cooperation.layout
@@ -103,15 +142,14 @@ levels:
     name: "Level 4"
     seed: 12345
     config_overwrite:
-      player_config:
-        speed_units_per_seconds: 300
       game:
-        time_limit_seconds: 10
+        time_limit_seconds: 300
       plates:
         clean_plates: 0
         dirty_plates: 0
         return_dirty: true
       orders:
+        serving_not_ordered_meals: false
         meals:
           all: false
           list:
@@ -127,8 +165,25 @@ levels:
           sample_on_dur_random_func:
             func: uniform
             kwargs:
-              a: 40
-              b: 50
+              a: 20
+              b: 30
+      hook_callbacks:
+        orders:
+          hooks: [ completed_order ]
+          callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
+          callback_class_kwargs:
+            time_dependence_func: !!python/name:cooperative_cuisine.scores.stepped_score ''
+            time_dependence_kwargs:
+              score_ratios: [ 0.5, 1, 1 ]
+              steps: [ 0, 0.25, 0.66 ]
+              round_decimals: 0
+            static_score: 20
+            score_on_specific_kwarg: meal_name
+            score_map:
+              Burger: 40
+              Salad: 20
+              Chips: 10
+              BurgerWithChips: 60
 
 num_players: 1
 num_bots: 0
diff --git a/cooperative_cuisine/environment.py b/cooperative_cuisine/environment.py
index dfe89d708e058d8232641cf37c1180dc802da1d4..90be31686eb64c7cd15a3a034cb5c2e2fc4edf34 100644
--- a/cooperative_cuisine/environment.py
+++ b/cooperative_cuisine/environment.py
@@ -504,7 +504,7 @@ class Environment:
                 "counters": [c.to_dict() for c in self.counters],
                 "kitchen": {"width": self.kitchen_width, "height": self.kitchen_height},
                 "score": self.score,
-                "orders": self.order_manager.order_state(),
+                "orders": self.order_manager.order_state(self.env_time),
                 "ended": self.game_ended,
                 "env_time": self.env_time.isoformat(),
                 "remaining_time": max(
diff --git a/cooperative_cuisine/hooks.py b/cooperative_cuisine/hooks.py
index d83daf7ff82a02b0c436f0bb79f9e92aec34eb4a..ea6d6c59d46637d3ed2795793af63e4a3308c0bd 100644
--- a/cooperative_cuisine/hooks.py
+++ b/cooperative_cuisine/hooks.py
@@ -423,6 +423,7 @@ Args:
     order (Order): the order that was fulfilled.
     meal (Item): The meal that was served.
     relative_order_time (timedelta): the time that the player needed to fulfill the order.
+    remaining_time_ratio (float): the ratio of the remaining time of the order relative to order duration.
     meal_name (str): name of the meal.
 """
 INIT_ORDERS = "init_orders"
diff --git a/cooperative_cuisine/orders.py b/cooperative_cuisine/orders.py
index 0b0529e0a39287b5dcf25bc5b494dba7e7fe7626..9a98314a352324fb787b32e1a8121d6aeb11d193 100644
--- a/cooperative_cuisine/orders.py
+++ b/cooperative_cuisine/orders.py
@@ -54,6 +54,7 @@ from cooperative_cuisine.hooks import (
     ORDER_EXPIRED,
 )
 from cooperative_cuisine.items import Item, Plate, ItemInfo
+from cooperative_cuisine.scores import ScoreViaHooks
 from cooperative_cuisine.state_representation import OrderState
 
 log = logging.getLogger(__name__)
@@ -185,6 +186,9 @@ class OrderManager:
 
         self.hook: Hooks = hook
         """Reference to the hook manager."""
+        self.score_callbacks = []
+        """List of score callbacks."""
+        self.find_score_hook_callbacks()
 
     def set_available_meals(self, available_meals):
         """Set the available meals from which orders can be generated.
@@ -204,6 +208,12 @@ class OrderManager:
             )
         self.next_relevant_time = next_relevant_time
 
+    def find_score_hook_callbacks(self):
+        """Find the score hook callback class."""
+        for hook in self.hook.hooks[COMPLETED_ORDER]:
+            if isinstance(hook, ScoreViaHooks):
+                self.score_callbacks.append(hook)
+
     def serve_meal(self, item: Item, env_time: datetime, player: str) -> bool:
         """Is called by the ServingWindow to serve a meal. Returns True if the meal can be served and should be
         "deleted" from the hands of the player."""
@@ -236,6 +246,10 @@ class OrderManager:
                         order=order,
                         meal=meal,
                         relative_order_time=env_time - order.start_time,
+                        remaining_time_ratio=(
+                            order.start_time + order.max_duration - env_time
+                        ).total_seconds()
+                        / order.max_duration.total_seconds(),
                         meal_name=meal.name,
                     )
                     return True
@@ -286,13 +300,21 @@ class OrderManager:
 
     def find_order_for_meal(self, meal) -> Tuple[Order, int] | None:
         """Get the order that will be fulfilled for a meal. At the moment the oldest order in the list that has the
-        same meal (name)."""
+        same meal (name).
+
+        Args:
+            meal: The meal to find the order for.
+        """
         for index, order in enumerate(self.open_orders):
             if order.meal.name == meal.name:
                 return order, index
 
-    def order_state(self) -> list[OrderState]:
-        """Similar to the `to_dict` in `Item` and `Counter`. Relevant for the state of the environment"""
+    def order_state(self, env_time: datetime) -> list[OrderState]:
+        """Similar to the `to_dict` in `Item` and `Counter`. Relevant for the state of the environment
+
+        Args:
+            env_time: The current time of the environment.
+        """
         return [
             {
                 "id": order.uuid,
@@ -300,6 +322,24 @@ class OrderManager:
                 "meal": order.meal.name,
                 "start_time": order.start_time.isoformat(),
                 "max_duration": order.max_duration.total_seconds(),
+                "score": sum(
+                    [
+                        sc.get_score(
+                            COMPLETED_ORDER,
+                            **{
+                                "meal": order.meal,
+                                "order": order,
+                                "relative_order_time": env_time - order.start_time,
+                                "remaining_time_ratio": (
+                                    order.start_time + order.max_duration - env_time
+                                ).total_seconds()
+                                / order.max_duration.total_seconds(),
+                                "meal_name": order.meal.name,
+                            },
+                        )[0]
+                        for sc in self.score_callbacks
+                    ]
+                ),
             }
             for order in self.open_orders
         ]
@@ -436,7 +476,7 @@ class RandomOrderGeneration(OrderGeneration):
                 self.create_random_next_time_delta(now)
                 return []
 
-        # print(self.number_cur_orders, self.num_needed_orders)
+        # (self.number_cur_orders, self.num_needed_orders)
 
         if self.num_needed_orders:
             # self.num_needed_orders -= len(new_finished_orders)
diff --git a/cooperative_cuisine/pygame_2d_vis/drawing.py b/cooperative_cuisine/pygame_2d_vis/drawing.py
index 6896a7bee8ec9332e444f68a95de22f39176b874..d69b12eebbadf21f1ee144d00521a61cf01c2229 100644
--- a/cooperative_cuisine/pygame_2d_vis/drawing.py
+++ b/cooperative_cuisine/pygame_2d_vis/drawing.py
@@ -97,6 +97,8 @@ class Visualizer:
             if "Gui" in config and "show_counter_centers" in config["Gui"]
             else False
         )
+        pygame.font.init()
+        self.font = pygame.font.SysFont("Arial", 20)
 
     def create_player_colors(self, n) -> None:
         """Create different colors for the players. The color hues are sampled uniformly in HSV-Space,
@@ -822,11 +824,7 @@ class Visualizer:
             config: Visualization configuration (loaded from yaml file) given as a dict.
 
         """
-        orders_width = width - 100
         orders_height = height
-        # order_screen = pygame.Surface(
-        #     (orders_width, orders_height),
-        # )
 
         bg_color = colors[config["GameWindow"]["background_color"]]
         pygame.draw.rect(screen, bg_color, screen.get_rect())
@@ -879,6 +877,11 @@ class Visualizer:
                 attention=percentage < 0.25,
             )
 
+            self.font.set_bold(True)
+
+            text_surface = self.font.render(str(order["score"]), True, (0, 0, 0))
+            screen.blit(text_surface, center)
+
     def save_state_image(
         self, grid_size: int, state: dict, filename: str | Path
     ) -> None:
diff --git a/cooperative_cuisine/pygame_2d_vis/gui.py b/cooperative_cuisine/pygame_2d_vis/gui.py
index 7d6fca9f7418cb593acbbc2e3af210c62a81709a..4ad01fc36073e8402dc4c0fe45842dd045e8a048 100644
--- a/cooperative_cuisine/pygame_2d_vis/gui.py
+++ b/cooperative_cuisine/pygame_2d_vis/gui.py
@@ -1440,7 +1440,7 @@ class PyGameGUI:
         if self.switch_score_color:
             self.count_frames_score_label += 1
 
-        duration_color_change = 90
+        duration_color_change = 60
         if score > self.last_score:
             self.score_label.update_theming(
                 '{"colours": {"normal_text": "#03b706"}, "font": { "size": 20, "bold": 1}}'
@@ -1553,15 +1553,16 @@ class PyGameGUI:
             "translations.level_name", text_kwargs={"level": self.level_info["name"]}
         )
 
-        graph_width = self.window_width * 0.6
         rows = 0
         for rg in self.level_info["recipe_graphs"]:
             rows += len(np.unique(np.array(list(rg["layout"].values()))[:, 1]))
         row_height = self.window_height / 14
-        container_width = self.window_width * 0.9
+        container_width = self.window_width * 0.98
         container_height = rows * row_height
         icon_size = row_height * 0.9
 
+        graph_width = container_width * 0.55
+
         main_container = pygame_gui.elements.UIPanel(
             relative_rect=pygame.Rect(
                 (0, 0),
@@ -1583,9 +1584,6 @@ class PyGameGUI:
 
             positions = np.array(list(rg["layout"].values()))
 
-            unique_x_vals = np.unique(positions[:, 0])
-
-
             height = row_height * len(np.unique(positions[:, 1]))
 
             graph_height = height * 0.9
@@ -1621,7 +1619,7 @@ class PyGameGUI:
 
             rect = pygame.Rect(
                 (0, 0),
-                (self.window_width / 5, height),
+                (self.window_width / 6, height),
             )
             label = pygame_gui.elements.UILabel(
                 text=f"translations.{meal}",
@@ -1633,17 +1631,33 @@ class PyGameGUI:
             )
 
             rect = graph_surface.get_rect()
-            rect.right = 0
             graph_image = pygame_gui.elements.UIImage(
                 relative_rect=rect,
                 image_surface=graph_surface,
                 manager=self.manager,
                 object_id="#recipe_graph",
                 container=container,
-                anchors={"centery": "centery", "right": "right"},
+                anchors={"center": "center"},
             )
             last_recipes_labels.append(container)
 
+            rect = pygame.Rect(
+                (0, 0),
+                (self.window_width / 6, height),
+            )
+            rect.right = 0
+            recipe_score_label = pygame_gui.elements.UILabel(
+                text="",
+                relative_rect=rect,
+                manager=self.manager,
+                container=container,
+                object_id="#recipe_name",
+                anchors={"centery": "centery", "right": "right"},
+            )
+            recipe_score_label.set_text(
+                "translations.recipe_score", text_kwargs={"score": str(rg["score"])}
+            )
+
         self.scroll_space_recipes.set_scrollable_area_dimensions(
             (self.window_width * 0.95, container_height)
         )
diff --git a/cooperative_cuisine/pygame_2d_vis/gui_theme.json b/cooperative_cuisine/pygame_2d_vis/gui_theme.json
index 5ceaf4397e562c1e82e53566b5f09e91598e41f9..153f1ad88332218811b1f0e164c0564512429593 100644
--- a/cooperative_cuisine/pygame_2d_vis/gui_theme.json
+++ b/cooperative_cuisine/pygame_2d_vis/gui_theme.json
@@ -64,7 +64,7 @@
       "normal_text": "#000000"
     },
     "font": {
-      "size": 20,
+      "size": 24,
       "bold": 1
     }
   },
diff --git a/cooperative_cuisine/pygame_2d_vis/locales/translations.de.json b/cooperative_cuisine/pygame_2d_vis/locales/translations.de.json
index 47579ce8519b642e48e78611225d37e7e037fdfd..4b417c16b808c02e81bcdf6ee3f9fa9b6180080f 100644
--- a/cooperative_cuisine/pygame_2d_vis/locales/translations.de.json
+++ b/cooperative_cuisine/pygame_2d_vis/locales/translations.de.json
@@ -32,9 +32,10 @@
     "Burger": "Burger:",
     "Pizza": "Pizza:",
     "Fish And Chips": "Fish and Chips:",
-    "Chips": "Pommes",
+    "Chips": "Pommes:",
     "Salad": "Salat:",
     "Fried Fish": "Backfisch:",
-    "Burger With Chips": "Burger mit Pommes:"
+    "Burger With Chips": "Burger mit Pommes:",
+    "recipe_score": "Punkte: %{score}"
   }
 }
\ No newline at end of file
diff --git a/cooperative_cuisine/pygame_2d_vis/locales/translations.en.json b/cooperative_cuisine/pygame_2d_vis/locales/translations.en.json
index 9f9c558bf762d3db59f73aacd127e71d19491853..d2290d1fd2747ccd98ef973045f2255d72d2dc6c 100644
--- a/cooperative_cuisine/pygame_2d_vis/locales/translations.en.json
+++ b/cooperative_cuisine/pygame_2d_vis/locales/translations.en.json
@@ -35,6 +35,7 @@
     "Chips": "Chips",
     "Salad": "Salad:",
     "Fried Fish": "Fried Fish:",
-    "Burger With Chips": "Burger with Chips:"
+    "Burger With Chips": "Burger with Chips:",
+    "recipe_score": "Points: %{score}"
   }
 }
\ No newline at end of file
diff --git a/cooperative_cuisine/scores.py b/cooperative_cuisine/scores.py
index 3bab87e92f29caec0903c3865c747757f3b0c188..eb8529381456cbd4b5d438964d6425d713ef2c35 100644
--- a/cooperative_cuisine/scores.py
+++ b/cooperative_cuisine/scores.py
@@ -39,18 +39,123 @@ hook_callbacks:
     callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
     callback_class_kwargs:
       static_score: -10
+
+The score can be modified based on the time remaining for the order to be completed.
+hook_callbacks:
+  orders:
+    hooks: [ completed_order ]
+    callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
+    callback_class_kwargs:
+    time_dependence_func: !!python/name:cooperative_cuisine.scores.linear_score ''
+      time_dependence_kwargs:
+        min_score_ratio: 0.3
+        round_decimals: 2
+      static_score: 100
+      score_on_specific_kwarg: meal_name
+      score_map: []
+
+    hooks: [ completed_order ]
+    callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
+    callback_class_kwargs:
+    time_dependence_func: !!python/name:cooperative_cuisine.scores.stepped_score ''
+      time_dependence_kwargs:
+        steps: [0.3, 0.6, 1.0]
+        ratios: [0.3, 0.6, 1.0]
+        round_decimals: 2
+      static_score: 100
+      score_on_specific_kwarg: meal_name
+      score_map: []
+
+    hooks: [ completed_order ]
+    callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
+    callback_class_kwargs:
+    time_dependence_func: !!python/name:cooperative_cuisine.scores.constant_score ''
+      time_dependence_kwargs: {}
+      static_score: 100
+      score_on_specific_kwarg: meal_name
+      score_map: []
 ```
 
 
 # Code Documentation
 """
+from __future__ import annotations
+
+from typing import Any, TYPE_CHECKING
 
-from typing import Any
+import numpy as np
 
-from cooperative_cuisine.environment import Environment
+if TYPE_CHECKING:
+    from cooperative_cuisine.environment import Environment
 from cooperative_cuisine.hooks import HookCallbackClass
 
 
+def constant_score(max_score: float, time_percentage: float = 1.0):
+    """Returns the constant score. No time dependence.
+
+    Args:
+        max_score: The maximum score to be returned.
+        time_percentage: The time percentage. Default is 1.0.
+    """
+    return max_score
+
+
+def linear_score(
+    max_score: float,
+    min_score_ratio: float = 0.0,
+    time_percentage: float = 1.0,
+    round_decimals: int = 0,
+):
+    """
+    Returns the linear score based on the time percentage.
+
+    Args:
+        max_score: Maximum possible score.
+        min_score_ratio: Minimum score ratio. Default is 0.0.
+        time_percentage: Time percentage of the order. Default is 1.0.
+        round_decimals: Number of decimals to round the score to. Default is 0.
+
+    Returns: Modified score based on the time percentage.
+    """
+    modified_score = float(
+        np.round(
+            max(max_score * time_percentage, max_score * min_score_ratio),
+            decimals=round_decimals,
+        )
+    )
+    return modified_score
+
+
+def stepped_score(
+    max_score: float,
+    steps: list[float],
+    score_ratios: list[float],
+    round_decimals: int = 0,
+    time_percentage: float = 1.0,
+):
+    """
+    Modifies the score based on a step function based on the time percentage.
+
+    Args:
+        max_score: Maximum possible score.
+        steps: Steps for the score ratios.
+        score_ratios: Ratios for the score based on the steps.
+        round_decimals: Number of decimals to round the score to. Default is 0.
+        time_percentage: Time percentage of the order. Default is 1.0.
+
+    Returns: Modified score based on the time percentage.
+
+    """
+    if len(steps) != len(score_ratios):
+        raise ValueError("steps and vals must have the same length")
+
+    for threshold, ratio in zip(reversed(steps), reversed(score_ratios)):
+        if max(time_percentage, 0) >= threshold:
+            return float(np.round(max_score * ratio, decimals=round_decimals))
+
+    assert False, "This should not happen."
+
+
 class ScoreViaHooks(HookCallbackClass):
     """
     Defines a class ScoreViaHooks that extends the HookCallbackClass.
@@ -71,6 +176,8 @@ class ScoreViaHooks(HookCallbackClass):
         static_score: float = 0,
         score_map: dict[str, float] = None,
         score_on_specific_kwarg: str = None,
+        time_dependence_func: callable = constant_score,
+        time_dependence_kwargs: dict[str, Any] = None,
         kwarg_filter: dict[str, Any] = None,
         **kwargs,
     ):
@@ -94,24 +201,47 @@ class ScoreViaHooks(HookCallbackClass):
         """Filtering condition for keyword arguments."""
         self.score_on_specific_kwarg: str = score_on_specific_kwarg
         """The specific keyword argument to score on."""
+        self.time_dependence_func: callable = time_dependence_func
+        """The function to calculate the score based on time."""
+        self.time_dependence_kwargs: dict[str, Any] = (
+            time_dependence_kwargs if time_dependence_kwargs else {}
+        )
+        """The keyword arguments to be passed to the time_dependence_func."""
 
-    def __call__(self, hook_ref: str, env: Environment, **kwargs):
+    def get_score(self, hook_ref: str, **kwargs):
         if self.score_on_specific_kwarg:
             if kwargs[self.score_on_specific_kwarg] in self.score_map:
-                self.env.increment_score(
-                    self.score_map[kwargs[self.score_on_specific_kwarg]],
-                    info=f"{hook_ref} - {kwargs[self.score_on_specific_kwarg]}",
-                )
+                score = self.score_map[kwargs[self.score_on_specific_kwarg]]
+                info = f"{hook_ref} - {kwargs[self.score_on_specific_kwarg]}"
             else:
-                self.env.increment_score(self.static_score, info=hook_ref)
+                score = self.static_score
+                info = hook_ref
         elif self.score_map and hook_ref in self.score_map:
             if self.kwarg_filter:
                 if self.kwarg_filter.items() <= kwargs.items():
-                    self.env.increment_score(
-                        self.score_map[hook_ref],
-                        info=f"{hook_ref} - {self.kwarg_filter}",
-                    )
+                    score = self.score_map[hook_ref]
+                    info = f"{hook_ref} - {self.kwarg_filter}"
+                else:
+                    score = 0
+                    info = "NO INFO?"
             else:
-                self.env.increment_score(self.score_map[hook_ref], info=hook_ref)
+                score = self.score_map[hook_ref]
+                info = hook_ref
         else:
-            self.env.increment_score(self.static_score, info=hook_ref)
+            score = self.static_score
+            info = hook_ref
+
+        if score:
+            if hook_ref == "completed_order":
+                ratio = kwargs["remaining_time_ratio"]
+            else:
+                ratio = 1.0
+            modified_score = self.time_dependence_func(
+                score, time_percentage=ratio, **self.time_dependence_kwargs
+            )
+            return modified_score, info
+        return 0, "NO INFO?"
+
+    def __call__(self, hook_ref: str, env: Environment, **kwargs):
+        score, info = self.get_score(hook_ref, **kwargs)
+        self.env.increment_score(score, info=info)
diff --git a/cooperative_cuisine/state_representation.py b/cooperative_cuisine/state_representation.py
index 209bf7d98ad3157f093071b23a479fd89563a637..68191b67fe3c3ee9b21b0b1e79c186e3a971c327 100644
--- a/cooperative_cuisine/state_representation.py
+++ b/cooperative_cuisine/state_representation.py
@@ -27,6 +27,8 @@ class OrderState(TypedDict):
     """Time of the creation of the order."""
     max_duration: float
     """Maximum duration of the order until it should be served."""
+    score: float | int
+    """Score of the order."""
 
 
 class EffectState(TypedDict):
diff --git a/cooperative_cuisine/validation.py b/cooperative_cuisine/validation.py
index cea549750ef51f2cbfc6b323cd8a3c6d14fb3eca..111edaf73d760b87e97e053b6b55b83420ae578c 100644
--- a/cooperative_cuisine/validation.py
+++ b/cooperative_cuisine/validation.py
@@ -4,6 +4,7 @@ import json
 import os
 import uuid
 import warnings
+from datetime import datetime, timedelta
 from typing import TypedDict, Tuple, Iterator, Set
 
 import networkx as nx
@@ -17,8 +18,9 @@ from cooperative_cuisine.counters import (
     PlateDispenser,
     Counter,
 )
+from cooperative_cuisine.hooks import COMPLETED_ORDER
 from cooperative_cuisine.items import ItemInfo, ItemType, Item
-from cooperative_cuisine.orders import OrderManager
+from cooperative_cuisine.orders import OrderManager, Order
 
 
 class MealGraphDict(TypedDict):
@@ -30,6 +32,8 @@ class MealGraphDict(TypedDict):
     """A list of tuples representing the edges between cooking steps."""
     layout: dict[str, Tuple[float, float]]
     """A dictionary mapping cooking step names to their layout coordinates."""
+    score: float
+    """The max possible score of the meal."""
 
 
 class Validation:
@@ -161,7 +165,26 @@ class Validation:
                                 current,
                             )
 
-        before_hash = "".join(sorted(str(sorted([sorted(i) for i in graph.edges]))))
+        dummy_order = Order(meal, datetime.now(), timedelta(seconds=1))
+        score = sum(
+            [
+                sc.get_score(
+                    COMPLETED_ORDER,
+                    **{
+                        "meal": dummy_order.meal,
+                        "order": dummy_order,
+                        "relative_order_time": timedelta(seconds=0),
+                        "remaining_time_ratio": 1.0,
+                        "meal_name": dummy_order.meal.name,
+                    },
+                )[0]
+                for sc in self.order_manager.score_callbacks
+            ]
+        )
+
+        before_hash = "".join(
+            sorted(str(sorted([sorted(i) for i in graph.edges])))
+        ) + str(score)
         h = hashlib.new("sha1")
         h.update(before_hash.encode())
         graph_hash = h.hexdigest()
@@ -186,6 +209,7 @@ class Validation:
                 "meal": meal.name,
                 "edges": list(graph.edges),
                 "layout": layout,
+                "score": score,
             }
             with open(generated_graph_layouts_path, "w") as f:
                 self.recipe_graph_dicts[graph_hash] = graph_dict