Skip to content
Snippets Groups Projects
Commit 4848c310 authored by Florian Schröder's avatar Florian Schröder
Browse files

fix bugs

parent 65f5fea4
No related branches found
No related tags found
1 merge request!27Resolve "Orders"
Pipeline #44013 failed
......@@ -15,13 +15,13 @@ orders:
b: 50
max_orders: 5
num_start_meals: 3
sample_on_dur: false
sample_on_dur: true
sample_on_dur_func:
func: uniform
kwargs:
a: 30
b: 50
sample_on_serving: true
a: 20
b: 30
sample_on_serving: false
score_calc_gen_kwargs:
other: 0
scores:
......
......@@ -433,7 +433,12 @@ class PyGameGUI:
pygame.draw.circle(screen, color, pos, radius)
def draw_item(
self, pos: npt.NDArray[float], item: Item, scale: float = 1.0, plate=False
self,
pos: npt.NDArray[float],
item: Item,
scale: float = 1.0,
plate=False,
screen=None,
):
"""Visualization of an item at the specified position. On a counter or in the hands of the player.
The visual composition of the item is read in from visualization.yaml file, where it is specified as
......@@ -443,6 +448,8 @@ class PyGameGUI:
pos: The position of the item to draw.
item: The item do be drawn in the game.
scale: Rescale the item by this factor.
screen: the pygame screen to draw on.
plate: item is on a plate (soup are is different on a plate and pot)
"""
if not isinstance(item, list):
......@@ -451,7 +458,10 @@ class PyGameGUI:
if "Soup" in item.name and plate:
item_key += "Plate"
self.draw_thing(
pos, self.visualization_config[item_key]["parts"], scale=scale
pos,
self.visualization_config[item_key]["parts"],
scale=scale,
screen=screen,
)
if isinstance(item, (Item, Plate)) and item.progress_percentage > 0.0:
......@@ -463,7 +473,9 @@ class PyGameGUI:
and item.content_ready.name in self.visualization_config
):
self.draw_thing(
pos, self.visualization_config[item.content_ready.name]["parts"]
pos,
self.visualization_config[item.content_ready.name]["parts"],
screen=screen,
)
else:
triangle_offsets = create_polygon(len(item.content_list), length=10)
......@@ -474,6 +486,7 @@ class PyGameGUI:
o,
scale=scale,
plate=isinstance(item, Plate),
screen=screen,
)
# if isinstance(item, Meal):
......@@ -549,36 +562,24 @@ class PyGameGUI:
self.timer_label.set_text(f"Time remaining: {display_time}")
def draw_orders(self, state):
# print(state["orders"])
# for o in state["orders"]:
# print(o.meal.name)
# orders = [
# "Burger",
# "TomatoSoupPlate",
# "OnionSoupPlate",
# "OnionSoupPlate",
# "OnionSoupPlate",
# "OnionSoupPlate",
# ]
orders = [o.meal.name for o in state["orders"]]
orders_width = self.game_width - 100
orders_height = self.screen_margin
self.orders_screen = pygame.Surface(
order_screen = pygame.Surface(
(orders_width, orders_height),
)
bg_color = colors[self.visualization_config["GameWindow"]["background_color"]]
pygame.draw.rect(self.orders_screen, bg_color, self.orders_screen.get_rect())
pygame.draw.rect(order_screen, bg_color, order_screen.get_rect())
order_rects_start = (orders_height // 2) - (self.grid_size // 2)
for idx, order in enumerate(orders):
for idx, order in enumerate([o.meal for o in state["orders"]]):
order_upper_left = [
order_rects_start + idx * self.grid_size * 1.5,
order_rects_start,
]
pygame.draw.rect(
self.orders_screen,
order_screen,
colors["red"],
pygame.Rect(
order_upper_left[0],
......@@ -594,27 +595,21 @@ class PyGameGUI:
self.draw_thing(
center,
self.visualization_config["Plate"]["parts"],
screen=self.orders_screen,
screen=order_screen,
)
self.draw_thing(
self.draw_item(
center,
self.visualization_config[order]["parts"],
screen=self.orders_screen,
order,
plate=True,
screen=order_screen,
)
orders_rect = self.orders_screen.get_rect()
orders_rect = order_screen.get_rect()
orders_rect.center = [
self.screen_margin + (orders_width // 2),
orders_height // 2,
]
self.main_window.blit(self.orders_screen, orders_rect)
self.orders_label = pygame_gui.elements.UILabel(
text="Orders:",
relative_rect=pygame.Rect(0, 0, self.screen_margin, self.screen_margin),
manager=self.manager,
object_id="#orders_label",
)
self.main_window.blit(order_screen, orders_rect)
def draw(self, state):
"""Main visualization function.
......@@ -732,6 +727,13 @@ class PyGameGUI:
object_id="#timer_label",
)
self.orders_label = pygame_gui.elements.UILabel(
text="Orders:",
relative_rect=pygame.Rect(0, 0, self.screen_margin, self.screen_margin),
manager=self.manager,
object_id="#orders_label",
)
def set_window_size(self, window_width, window_height, game_width, game_height):
self.game_screen = pygame.Surface(
(
......
......@@ -6,14 +6,14 @@ from collections import deque
from datetime import datetime, timedelta
from typing import Callable, Tuple, Any, Deque
from overcooked_simulator.game_items import Item, Plate
from overcooked_simulator.game_items import Item, Plate, ItemInfo
log = logging.getLogger(__name__)
@dataclasses.dataclass
class Order:
meal: Item
meal: ItemInfo
start_time: datetime
max_duration: timedelta
score_calc: Callable[[timedelta, ...], float]
......@@ -44,8 +44,8 @@ class Order:
class OrderGeneration:
def __init__(self, available_meals: dict[str, Item], **kwargs):
self.available_meals: list[Item] = list(available_meals.values())
def __init__(self, available_meals: dict[str, ItemInfo], **kwargs):
self.available_meals: list[ItemInfo] = list(available_meals.values())
@abstractmethod
def init_orders(self, now) -> list[Order]:
......@@ -67,16 +67,16 @@ class RandomOrderKwarg:
max_orders: int
duration_sample: dict
score_calc_gen_func: Callable[
[Item, timedelta, datetime, Any], Callable[[timedelta, Order], float]
[ItemInfo, timedelta, datetime, Any], Callable[[timedelta, Order], float]
]
score_calc_gen_kwargs: dict
class RandomOrderGeneration(OrderGeneration):
def __init__(self, available_meals: dict[str, Item], **kwargs):
def __init__(self, available_meals: dict[str, ItemInfo], **kwargs):
super().__init__(available_meals, **kwargs)
self.kwargs: RandomOrderKwarg = RandomOrderKwarg(**kwargs["kwargs"])
self.next_order_time: datetime | None = None
self.next_order_time: datetime | None = datetime.max
self.number_cur_orders = 0
self.needed_orders: int = 0
"""For the sample on dur but when it was restricted due to max order number."""
......@@ -97,35 +97,33 @@ class RandomOrderGeneration(OrderGeneration):
self.number_cur_orders -= len(new_finished_orders)
if self.kwargs.sample_on_serving:
if new_finished_orders:
self.number_cur_orders += len(new_finished_orders)
return self.create_orders_for_meals(
random.choices(self.available_meals, k=len(new_finished_orders)),
now,
True,
)
if self.kwargs.sample_on_dur:
if self.needed_orders:
self.needed_orders -= len(new_finished_orders)
self.needed_orders = max(self.needed_orders, 0)
self.number_cur_orders += len(new_finished_orders)
self.create_random_next_time_delta(now)
return []
if self.needed_orders:
self.needed_orders -= len(new_finished_orders)
self.needed_orders = max(self.needed_orders, 0)
self.number_cur_orders += len(new_finished_orders)
return self.create_orders_for_meals(
random.choices(self.available_meals, k=len(new_finished_orders)),
now,
)
if self.next_order_time <= now:
if self.number_cur_orders >= self.kwargs.max_orders:
self.needed_orders += 1
else:
if self.kwargs.sample_on_dur:
self.create_random_next_time_delta(now)
else:
self.next_order_time = datetime.max
self.number_cur_orders += 1
return self.create_orders_for_meals(
random.choices(self.available_meals, k=len(new_finished_orders)),
[random.choice(self.available_meals)],
now,
)
if self.next_order_time < now:
if self.number_cur_orders >= self.kwargs.max_orders:
self.needed_orders += 1
else:
self.create_random_next_time_delta(now)
self.number_cur_orders += 1
return self.create_orders_for_meals(
random.choice(self.available_meals),
now,
)
return []
def create_orders_for_meals(
self, meals: list[Item], now: datetime, no_time_limit: bool = False
self, meals: list[ItemInfo], now: datetime, no_time_limit: bool = False
) -> list[Order]:
orders = []
for meal in meals:
......@@ -158,13 +156,14 @@ class RandomOrderGeneration(OrderGeneration):
return orders
def create_random_next_time_delta(self, now: datetime):
self.next_order_time = timedelta(
self.next_order_time = now + timedelta(
seconds=int(
getattr(random, self.kwargs.duration_sample["func"])(
**self.kwargs.duration_sample["kwargs"]
getattr(random, self.kwargs.sample_on_dur_func["func"])(
**self.kwargs.sample_on_dur_func["kwargs"]
)
)
)
log.info(f"Next order in {self.next_order_time}")
def simple_score_calc_gen_func(
......@@ -182,7 +181,7 @@ def simple_score_calc_gen_func(
class OrderAndScoreManager:
def __init__(self, order_config, available_meals: dict[str, Item]):
def __init__(self, order_config, available_meals: dict[str, ItemInfo]):
self.score = 0
self.order_gen: OrderGeneration = order_config["order_gen_class"](
available_meals=available_meals, kwargs=order_config["kwargs"]
......@@ -196,7 +195,17 @@ class OrderAndScoreManager:
# TODO log who / which player served which meal -> for split scores
self.served_meals: list[Tuple[Item, datetime]] = []
self.last_finished = []
self.penalty_timers = []
self.next_relevant_time = datetime.max
def update_next_relevant_time(self):
next_relevant_time = datetime.max
for order in self.open_orders:
next_relevant_time = min(
next_relevant_time, order.start_time + order.max_duration
)
for penalty in order._timed_penalties:
next_relevant_time = min(next_relevant_time, penalty[0])
self.next_relevant_time = next_relevant_time
def serve_meal(self, item: Item, env_time: datetime) -> bool:
if isinstance(item, Plate):
......@@ -250,26 +259,28 @@ class OrderAndScoreManager:
)
self.open_orders.extend(new_orders)
self.last_finished = []
remove_orders = []
for index, order in enumerate(self.open_orders):
if now >= order.start_time + order.max_duration:
remove_orders.append(index)
remove_penalties = []
for index, (penalty_time, penalty) in enumerate(order.timed_penalties):
if penalty_time < now:
self.score -= penalty
remove_penalties.append(index)
for index in remove_penalties:
# or del order.timed_penalties[index]
order.timed_penalties.pop(index)
for remove_order in remove_orders:
del self.open_orders[remove_order]
if new_orders or self.next_relevant_time <= now:
remove_orders = []
for index, order in enumerate(self.open_orders):
if now >= order.start_time + order.max_duration:
remove_orders.append(index)
remove_penalties = []
for i, (penalty_time, penalty) in enumerate(order.timed_penalties):
if penalty_time < now:
self.score -= penalty
remove_penalties.append(i)
for i in remove_penalties:
# or del order.timed_penalties[index]
order.timed_penalties.pop(i)
for remove_order in remove_orders:
del self.open_orders[remove_order]
self.update_next_relevant_time()
def find_order_for_meal(self, meal) -> Tuple[Order, int] | None:
for neg_index, order in enumerate(reversed(self.open_orders)):
for neg_index, order in enumerate(self.open_orders):
if order.meal.name == meal.name:
return order, len(self.open_orders) - neg_index - 1
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment