Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • scs/cocosy/cooperative-cuisine
1 result
Show changes
Commits on Source (8)
  • Florian Schröder's avatar
    Refactor recorder and hooks setup in config files · 6a671b9e
    Florian Schröder authored
    This commit refactors the setup of recorders and hooks in several configuration files. It simplifies the YAML structure, renames "extra_setup_functions" to "hook_callbacks", and replaces "log_path" with "record_path". This makes the configurations cleaner and more intuitive. The update also removes the "func" and "kwargs" in the extra setup functions. Now only hooks are registered. This change should not affect functionality, because until now only hooks were registered as extra setup functions.
    6a671b9e
  • Florian Schröder's avatar
    Add pygame tests · 70a61b45
    Florian Schröder authored
    This commit introduces a new test suite for the pygame functionality. It includes tests for color formatting and uniqueness, angle calculations, and proper initialization of the Visualizer. The tests aim to enhance game integrity and avoid potential issues with visualization.
    70a61b45
  • Florian Schröder's avatar
    Update comparisons and variable types, add tests · 14a081cc
    Florian Schröder authored
    This commit modifies comparison operators for timers to be less than or equal in various scripts. It also changes variable types explicitly in scores.py and adds several new tests for functionalities like effects, scores, information messages, trashing function etc. Additional updates include changes in values for certain default arguments in command line parser for generating images in the script for 2D visualization.
    14a081cc
  • Florian Schröder's avatar
    Add test for tutorial connectivity and game item tests · c86635e6
    Florian Schröder authored
    Expanded the tests in the 'test_study_server.py' file to include testing for tutorial connectivity. Added tests in 'test_start.py' to test the functionality of PlateDispenser and Sink game items. This included tests to validate the handling of dirty and clean plates and testing item drops and pick-ups. Various adjustments were made to players' positions to accommodate the tests.
    c86635e6
  • Florian Schröder's avatar
    Merge branch '112-more-tests' into 'dev' · 42436541
    Florian Schröder authored
    Resolve "More tests"
    
    Closes #112
    
    See merge request scs/cocosy/overcooked-simulator!79
    42436541
  • Florian Schröder's avatar
    Merge remote-tracking branch 'origin/dev' into... · 09e9113b
    Florian Schröder authored
    Merge remote-tracking branch 'origin/dev' into 115-remove-repitition-of-hook-callback-class-in-env-config
    09e9113b
  • Florian Schröder's avatar
    Refactor test_start.py for hook callback changes · 5d15016c
    Florian Schröder authored
    Removed the 'hooks_via_callback_class' usage and replaced it with 'hook_callbacks'. The 'extra_setup_functions' field has been renamed to 'hook_callbacks' to provide a more accurate description of its role. The callback logic has consequently been adjusted, reducing verbosity and simplifying the code.
    5d15016c
  • Florian Schröder's avatar
    Merge branch '115-remove-repitition-of-hook-callback-class-in-env-config' into 'dev' · fa0c937f
    Florian Schröder authored
    Resolve "Remove repitition of Hook callback class in env config"
    
    Closes #115
    
    See merge request scs/cocosy/overcooked-simulator!77
    fa0c937f
Showing
with 868 additions and 503 deletions
......@@ -323,7 +323,7 @@ player_config:
effect_manager: # fire effect
...
extra_setup_functions: # scores, recording, msgs, etc.
hook_callbacks: # scores, recording, msgs, etc.
...
```
......
......@@ -98,114 +98,96 @@ effect_manager:
fire_burns_ingredients_and_meals: true
extra_setup_functions:
hook_callbacks:
# # --------------- Scoring ---------------
orders:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ completed_order ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: 20
score_on_specific_kwarg: meal_name
score_map:
Burger: 15
OnionSoup: 10
Salad: 5
TomatoSoup: 10
hooks: [ completed_order ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: 20
score_on_specific_kwarg: meal_name
score_map:
Burger: 15
OnionSoup: 10
Salad: 5
TomatoSoup: 10
not_ordered_meals:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ serve_not_ordered_meal ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: 2
hooks: [ serve_not_ordered_meal ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: 2
trashcan_usages:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ trashcan_usage ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: -5
hooks: [ trashcan_usage ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: -5
expired_orders:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ order_expired ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: -10
# # --------------- Recording ---------------
hooks: [ order_expired ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: -10
# --------------- Recording ---------------
# json_states:
# func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
# kwargs:
# hooks: [ json_state ]
# callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
# callback_class_kwargs:
# log_path: USER_LOG_DIR/ENV_NAME/json_states.jsonl
# hooks: [ json_state ]
# callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
# callback_class_kwargs:
# record_path: USER_LOG_DIR/ENV_NAME/json_states.jsonl
actions:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ pre_perform_action ]
callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
callback_class_kwargs:
log_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
hooks: [ pre_perform_action ]
callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
callback_class_kwargs:
record_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
random_env_events:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ order_duration_sample, plate_out_of_kitchen_time ]
callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
callback_class_kwargs:
log_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
add_hook_ref: true
hooks: [ order_duration_sample, plate_out_of_kitchen_time ]
callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
callback_class_kwargs:
record_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
add_hook_ref: true
env_configs:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ env_initialized, item_info_config ]
callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
callback_class_kwargs:
log_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
add_hook_ref: true
hooks: [ env_initialized, item_info_config ]
callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
callback_class_kwargs:
record_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
add_hook_ref: true
# Game event recording
game_events:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks:
- post_counter_pick_up
- post_counter_drop_off
- post_dispenser_pick_up
- cutting_board_100
- player_start_interaction
- player_end_interact
- post_serving
- no_serving
- dirty_plate_arrives
- trashcan_usage
- plate_cleaned
- added_plate_to_sink
- drop_on_sink_addon
- pick_up_from_sink_addon
- serve_not_ordered_meal
- serve_without_plate
- completed_order
- new_orders
- order_expired
- action_on_not_reachable_counter
- new_fire
- fire_spreading
- drop_off_on_cooking_equipment
- players_collide
- post_plate_dispenser_pick_up
- post_plate_dispenser_drop_off
- on_item_transition
- progress_started
- progress_finished
- content_ready
hooks:
- post_counter_pick_up
- post_counter_drop_off
- post_dispenser_pick_up
- cutting_board_100
- player_start_interaction
- player_end_interact
- post_serving
- no_serving
- dirty_plate_arrives
- trashcan_usage
- plate_cleaned
- added_plate_to_sink
- drop_on_sink_addon
- pick_up_from_sink_addon
- serve_not_ordered_meal
- serve_without_plate
- completed_order
- new_orders
- order_expired
- action_on_not_reachable_counter
- new_fire
- fire_spreading
- drop_off_on_cooking_equipment
- players_collide
- post_plate_dispenser_pick_up
- post_plate_dispenser_drop_off
- on_item_transition
- progress_started
- progress_finished
- content_ready
callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
callback_class_kwargs:
log_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
add_hook_ref: true
callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
callback_class_kwargs:
record_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
add_hook_ref: true
# info_msg:
......
......@@ -98,127 +98,105 @@ effect_manager:
fire_burns_ingredients_and_meals: true
extra_setup_functions:
hook_callbacks:
# # --------------- Scoring ---------------
orders:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ completed_order ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: 20
score_on_specific_kwarg: meal_name
score_map:
Burger: 15
OnionSoup: 10
Salad: 5
TomatoSoup: 10
hooks: [ completed_order ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: 20
score_on_specific_kwarg: meal_name
score_map:
Burger: 15
OnionSoup: 10
Salad: 5
TomatoSoup: 10
not_ordered_meals:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ serve_not_ordered_meal ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: 2
hooks: [ serve_not_ordered_meal ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: 2
trashcan_usages:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ trashcan_usage ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: -5
hooks: [ trashcan_usage ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: -5
expired_orders:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ order_expired ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: -10
hooks: [ order_expired ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: -10
# # --------------- Recording ---------------
# json_states:
# func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
# kwargs:
# hooks: [ json_state ]
# callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
# callback_class_kwargs:
# log_path: USER_LOG_DIR/ENV_NAME/json_states.jsonl
# hooks: [ json_state ]
# callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
# callback_class_kwargs:
# record_path: USER_LOG_DIR/ENV_NAME/json_states.jsonl
# Game event recording
game_events:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks:
- post_counter_pick_up
- post_counter_drop_off
- post_dispenser_pick_up
- cutting_board_100
- player_start_interaction
- player_end_interact
- post_serving
- no_serving
- dirty_plate_arrives
- trashcan_usage
- plate_cleaned
- added_plate_to_sink
- drop_on_sink_addon
- pick_up_from_sink_addon
- serve_not_ordered_meal
- serve_without_plate
- completed_order
- new_orders
- order_expired
- action_on_not_reachable_counter
- new_fire
- fire_spreading
- drop_off_on_cooking_equipment
- players_collide
- post_plate_dispenser_pick_up
- post_plate_dispenser_drop_off
- on_item_transition
- progress_started
- progress_finished
- content_ready
hooks:
- post_counter_pick_up
- post_counter_drop_off
- post_dispenser_pick_up
- cutting_board_100
- player_start_interaction
- player_end_interact
- post_serving
- no_serving
- dirty_plate_arrives
- trashcan_usage
- plate_cleaned
- added_plate_to_sink
- drop_on_sink_addon
- pick_up_from_sink_addon
- serve_not_ordered_meal
- serve_without_plate
- completed_order
- new_orders
- order_expired
- action_on_not_reachable_counter
- new_fire
- fire_spreading
- drop_off_on_cooking_equipment
- players_collide
- post_plate_dispenser_pick_up
- post_plate_dispenser_drop_off
- on_item_transition
- progress_started
- progress_finished
- content_ready
callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
callback_class_kwargs:
log_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
add_hook_ref: true
callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
callback_class_kwargs:
record_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
add_hook_ref: true
actions:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ pre_perform_action ]
callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
callback_class_kwargs:
log_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
hooks: [ pre_perform_action ]
callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
callback_class_kwargs:
record_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
random_env_events:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ order_duration_sample, plate_out_of_kitchen_time ]
callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
callback_class_kwargs:
log_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
add_hook_ref: true
hooks: [ order_duration_sample, plate_out_of_kitchen_time ]
callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
callback_class_kwargs:
record_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
add_hook_ref: true
env_configs:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ env_initialized, item_info_config ]
callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
callback_class_kwargs:
log_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
add_hook_ref: true
hooks: [ env_initialized, item_info_config ]
callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
callback_class_kwargs:
record_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
add_hook_ref: true
# info_msg:
# func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
# kwargs:
# hooks: [ cutting_board_100 ]
# log_class: !!python/name:cooperative_cuisine.info_msg.InfoMsgManager ''
# log_class_kwargs:
# msg: Glückwunsch du hast was geschnitten!
# hooks: [ cutting_board_100 ]
# record_class: !!python/name:cooperative_cuisine.info_msg.InfoMsgManager ''
# record_class_kwargs:
# msg: Glückwunsch du hast was geschnitten!
# fire_msg:
# func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
# kwargs:
# hooks: [ new_fire ]
# log_class: !!python/name:cooperative_cuisine.info_msg.InfoMsgManager ''
# log_class_kwargs:
# msg: Feuer, Feuer, Feuer
# level: Warning
# hooks: [ new_fire ]
# record_class: !!python/name:cooperative_cuisine.info_msg.InfoMsgManager ''
# record_class_kwargs:
# msg: Feuer, Feuer, Feuer
# level: Warning
......@@ -97,127 +97,105 @@ effect_manager:
fire_burns_ingredients_and_meals: true
extra_setup_functions:
hook_callbacks:
# # --------------- Scoring ---------------
orders:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ completed_order ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: 20
score_on_specific_kwarg: meal_name
score_map:
Burger: 15
OnionSoup: 10
Salad: 5
TomatoSoup: 10
hooks: [ completed_order ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: 20
score_on_specific_kwarg: meal_name
score_map:
Burger: 15
OnionSoup: 10
Salad: 5
TomatoSoup: 10
not_ordered_meals:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ serve_not_ordered_meal ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: 2
hooks: [ serve_not_ordered_meal ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: 2
trashcan_usages:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ trashcan_usage ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: -5
hooks: [ trashcan_usage ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: -5
expired_orders:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ order_expired ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: -10
hooks: [ order_expired ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: -10
# # --------------- Recording ---------------
# json_states:
# func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
# kwargs:
# hooks: [ json_state ]
# callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
# callback_class_kwargs:
# log_path: USER_LOG_DIR/ENV_NAME/json_states.jsonl
# hooks: [ json_state ]
# callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
# callback_class_kwargs:
# record_path: USER_LOG_DIR/ENV_NAME/json_states.jsonl
actions:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ pre_perform_action ]
callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
callback_class_kwargs:
log_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
hooks: [ pre_perform_action ]
callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
callback_class_kwargs:
record_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
random_env_events:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ order_duration_sample, plate_out_of_kitchen_time ]
callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
callback_class_kwargs:
log_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
add_hook_ref: true
hooks: [ order_duration_sample, plate_out_of_kitchen_time ]
callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
callback_class_kwargs:
record_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
add_hook_ref: true
env_configs:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ env_initialized, item_info_config ]
callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
callback_class_kwargs:
log_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
add_hook_ref: true
hooks: [ env_initialized, item_info_config ]
callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
callback_class_kwargs:
record_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
add_hook_ref: true
# Game event recording
game_events:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks:
- post_counter_pick_up
- post_counter_drop_off
- post_dispenser_pick_up
- cutting_board_100
- player_start_interaction
- player_end_interact
- post_serving
- no_serving
- dirty_plate_arrives
- trashcan_usage
- plate_cleaned
- added_plate_to_sink
- drop_on_sink_addon
- pick_up_from_sink_addon
- serve_not_ordered_meal
- serve_without_plate
- completed_order
- new_orders
- order_expired
- action_on_not_reachable_counter
- new_fire
- fire_spreading
- drop_off_on_cooking_equipment
- players_collide
- post_plate_dispenser_pick_up
- post_plate_dispenser_drop_off
- on_item_transition
- progress_started
- progress_finished
- content_ready
hooks:
- post_counter_pick_up
- post_counter_drop_off
- post_dispenser_pick_up
- cutting_board_100
- player_start_interaction
- player_end_interact
- post_serving
- no_serving
- dirty_plate_arrives
- trashcan_usage
- plate_cleaned
- added_plate_to_sink
- drop_on_sink_addon
- pick_up_from_sink_addon
- serve_not_ordered_meal
- serve_without_plate
- completed_order
- new_orders
- order_expired
- action_on_not_reachable_counter
- new_fire
- fire_spreading
- drop_off_on_cooking_equipment
- players_collide
- post_plate_dispenser_pick_up
- post_plate_dispenser_drop_off
- on_item_transition
- progress_started
- progress_finished
- content_ready
callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
callback_class_kwargs:
log_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
add_hook_ref: true
callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
callback_class_kwargs:
record_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
add_hook_ref: true
# info_msg:
# func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
# kwargs:
# hooks: [ cutting_board_100 ]
# log_class: !!python/name:cooperative_cuisine.info_msg.InfoMsgManager ''
# log_class_kwargs:
# msg: Glückwunsch du hast was geschnitten!
# hooks: [ cutting_board_100 ]
# record_class: !!python/name:cooperative_cuisine.info_msg.InfoMsgManager ''
# record_class_kwargs:
# msg: Glückwunsch du hast was geschnitten!
# fire_msg:
# func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
# kwargs:
# hooks: [ new_fire ]
# log_class: !!python/name:cooperative_cuisine.info_msg.InfoMsgManager ''
# log_class_kwargs:
# msg: Feuer, Feuer, Feuer
# level: Warning
# hooks: [ new_fire ]
# record_class: !!python/name:cooperative_cuisine.info_msg.InfoMsgManager ''
# record_class_kwargs:
# msg: Feuer, Feuer, Feuer
# level: Warning
......@@ -94,4 +94,4 @@ effect_manager:
fire_burns_ingredients_and_meals: true
extra_setup_functions:
\ No newline at end of file
hook_callbacks:
\ No newline at end of file
......@@ -684,10 +684,10 @@ class PlateDispenser(Counter):
def progress(self, passed_time: timedelta, now: datetime):
"""Check if plates arrive from outside the kitchen and add a dirty plate accordingly"""
if self.next_plate_time < now:
if self.next_plate_time <= now:
idx_delete = []
for i, times in enumerate(self.out_of_kitchen_timer):
if times < now:
if times <= now:
self.hook(DIRTY_PLATE_ARRIVES, counter=self, times=times, now=now)
idx_delete.append(i)
log.debug("Add dirty plate")
......
......@@ -163,9 +163,9 @@ class FireEffectManager(EffectManager):
self.active_effects.append((effect, target))
# reset new effects
self.new_effects = []
if self.next_finished_timer < now:
if self.next_finished_timer <= now:
for effect, target in self.active_effects:
if self.effect_to_timer[effect.uuid] < now:
if self.effect_to_timer[effect.uuid] <= now:
if isinstance(target, Item):
target = find_item_on_counters(target.uuid, self.counters)
if target:
......
......@@ -51,6 +51,7 @@ from cooperative_cuisine.hooks import (
ACTION_INTERACT_START,
ITEM_INFO_CONFIG,
POST_STEP,
hooks_via_callback_class,
)
from cooperative_cuisine.items import (
ItemInfo,
......@@ -90,8 +91,8 @@ class EnvironmentConfig(TypedDict):
"""Configuration about the player characters."""
layout_chars: dict[str, str]
"""Definition of which characters in the layout file correspond to which kitchen counter."""
extra_setup_functions: dict[str, dict]
"""Configuration of extra setup functions, for example hook behavior."""
hook_callbacks: dict[str, dict]
"""Configuration of callbacks via HookCallbackClass."""
effect_manager: dict
"""Config of different effects in the environment, which control for example fire behavior."""
......@@ -184,7 +185,7 @@ class Environment:
"player_config"
].view_range
self.extra_setup_functions()
self.hook_callbacks()
self.layout_config: str = layout_config
"""The layout config for the environment"""
......@@ -570,16 +571,14 @@ class Environment:
"""
self.hook.register_callback(hook_ref, callback)
def extra_setup_functions(self):
def hook_callbacks(self):
"""Executes extra setup functions specified in the environment configuration."""
if self.environment_config["extra_setup_functions"]:
for function_name, function_def in self.environment_config[
"extra_setup_functions"
if self.environment_config["hook_callbacks"]:
for callback_name, setup_kwargs in self.environment_config[
"hook_callbacks"
].items():
log.info(f"Setup function {function_name}")
function_def["func"](
name=function_name, env=self, **function_def["kwargs"]
)
log.info(f"Setup hook callback {callback_name}")
hooks_via_callback_class(name=callback_name, env=self, **setup_kwargs)
def increment_score(self, score: int | float, info: str = ""):
"""Add a value to the current score and log it."""
......
......@@ -2,7 +2,7 @@
You can add callbacks at specific points in the environment.
This "hook" mechanism is defined here.
You can add hooks via the `environment_config` under `extra_setup_functions` and the here defined
You can add hooks via the `environment_config` under `hook_callbacks` and the here defined
`hooks_via_callback_class` function.
Each hook get different kwargs. But `env` with the environment object and `hook_ref` with the name of the hook are
......@@ -229,7 +229,7 @@ def hooks_via_callback_class(
callback_class: Type[HookCallbackClass],
callback_class_kwargs: dict[str, Any],
):
"""Function to reference in the `environment_config.yml` to add functionality via hooks and a configured callback class.
"""Setup hook callback class.
Args:
name: A string representing the name of the callback class instance.
......
"""Based on hooks, text-based info msgs can be displayed.
```yaml
extra_setup_functions:
hook_callbacks:
info_msg:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ cutting_board_100 ]
callback_class: !!python/name:cooperative_cuisine.info_msg.InfoMsgManager ''
callback_class_kwargs:
msg: Glückwunsch du hast was geschnitten!
fire_msg:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ new_fire ]
callback_class: !!python/name:cooperative_cuisine.info_msg.InfoMsgManager ''
callback_class_kwargs:
msg: Feuer, Feuer, Feuer
level: Warning
hooks: [ cutting_board_100 ]
callback_class: !!python/name:cooperative_cuisine.info_msg.InfoMsgManager ''
callback_class_kwargs:
msg: Glückwunsch du hast was geschnitten!
fire_msg:
hooks: [ new_fire ]
callback_class: !!python/name:cooperative_cuisine.info_msg.InfoMsgManager ''
callback_class_kwargs:
msg: Feuer, Feuer, Feuer
level: Warning
```
"""
......@@ -95,7 +91,7 @@ class InfoMsgManager(HookCallbackClass):
for player_id, msgs in env.info_msgs_per_player.items():
delete_msgs = []
for idx, msg in enumerate(msgs):
if msg["end_time"] < env.env_time:
if msg["end_time"] <= env.env_time:
delete_msgs.append(idx)
for idx in reversed(delete_msgs):
msgs.pop(idx)
......@@ -2,6 +2,7 @@ import argparse
import colorsys
import json
import os
import sys
from datetime import datetime, timedelta
from pathlib import Path
......@@ -1002,7 +1003,21 @@ def generate_recipe_images(config: dict, folder_path: str | Path):
pygame.image.save(screen, f"{folder_path}/{graph_dict['meal']}.png")
if __name__ == "__main__":
def main(args):
"""
Runs the Cooperative Cuisine Image Generation process.
This method takes command line arguments to specify the state file, visualization configuration file, and output file for the generated image. It then reads the visualization configuration
* file and state file, and calls the 'save_screenshot' and 'generate_recipe_images' methods to generate the image.
Args:
-s, --state: A command line argument of type `argparse.FileType("r", encoding="UTF-8")`. Specifies the state file to use for image generation. If not provided, the default value is 'ROOT_DIR / "pygame_2d_vis" / "sample_state.json"'.
-v, --visualization_config: A command line argument of type `argparse.FileType("r", encoding="UTF-8")`. Specifies the visualization configuration file to use for image generation. If not provided, the default value is 'ROOT_DIR / "pygame_2d_vis" / "visualization.yaml"'.
-o, --output_file: A command line argument of type `str`. Specifies the output file path for the generated image. If not provided, the default value is 'ROOT_DIR / "generated" / "screenshot.jpg"'.
"""
parser = argparse.ArgumentParser(
prog="Cooperative Cuisine Image Generation",
description="Generate images for a state in json.",
......@@ -1024,12 +1039,16 @@ if __name__ == "__main__":
"-o",
"--output_file",
type=str,
default=ROOT_DIR / "pygame_2d_vis" / "generated" / "screenshot.jpg",
default=ROOT_DIR / "generated" / "screenshot.jpg",
)
args = parser.parse_args()
args = parser.parse_args(args)
with open(args.visualization_config, "r") as f:
viz_config = yaml.safe_load(f)
with open(args.state, "r") as f:
state = json.load(f)
save_screenshot(state, viz_config, args.output_file)
generate_recipe_images(viz_config, args.output_file.parent)
if __name__ == "__main__":
main(sys.argv[1:])
......@@ -72,14 +72,14 @@ def simulate(
You can record the relevant files via hooks in the environment_config:
```yaml
extra_setup_functions
hook_callbacks
env_configs:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ env_initialized, item_info_config ]
callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
callback_class_kwargs:
log_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
record_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
add_hook_ref: true
actions:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
......@@ -87,7 +87,7 @@ def simulate(
hooks: [ pre_perform_action ]
callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
callback_class_kwargs:
log_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
record_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
```
You can call simulation function via the command line. For example by replacing the ENVIRONMENT_ID (Linux system) or the complete path:
......@@ -219,7 +219,7 @@ def from_json_states(
hooks: [ json_state ]
callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
callback_class_kwargs:
log_path: USER_LOG_DIR/ENV_NAME/json_states.jsonl
record_path: USER_LOG_DIR/ENV_NAME/json_states.jsonl
```
You can call this function via the command line:
......
......@@ -7,42 +7,35 @@ https://pypi.org/project/platformdirs/) -> `user_log_dir`.
- `ENV_NAME` to the name of the environment.
```yaml
extra_setup_functions:
hook_callbacks:
json_states:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ json_state ]
callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
callback_class_kwargs:
log_path: USER_LOG_DIR/ENV_NAME/json_states.jsonl
hooks: [ json_state ]
callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
callback_class_kwargs:
record_path: USER_LOG_DIR/ENV_NAME/json_states.jsonl
actions:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ pre_perform_action ]
callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
callback_class_kwargs:
log_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
hooks: [ pre_perform_action ]
callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
callback_class_kwargs:
record_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
random_env_events:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ order_duration_sample, plate_out_of_kitchen_time ]
callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
callback_class_kwargs:
log_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
add_hook_ref: true
hooks: [ order_duration_sample, plate_out_of_kitchen_time ]
callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
callback_class_kwargs:
record_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
add_hook_ref: true
env_configs:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ env_initialized, item_info_config ]
callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
callback_class_kwargs:
log_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
add_hook_ref: true
hooks: [ env_initialized, item_info_config ]
callback_class: !!python/name:cooperative_cuisine.recording.FileRecorder ''
callback_class_kwargs:
record_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
add_hook_ref: true
```
"""
import json
import logging
import os
import sys
import traceback
from pathlib import Path
from string import Template
......@@ -68,7 +61,7 @@ class FileRecorder(HookCallbackClass):
self,
name: str,
env: Environment,
log_path: str = "USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl",
record_path: str = "USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl",
add_hook_ref: bool = False,
**kwargs,
):
......@@ -77,19 +70,19 @@ class FileRecorder(HookCallbackClass):
Args:
name (str): The name of the recorder. This name is used to replace the placeholder "LOG_RECORD_NAME" in the default log file path.
env (Environment): The environment in which the recorder is being used.
log_path (str, optional): The path to the log file. Defaults to "USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl".
record_path (str, optional): The path to the log file. Defaults to "USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl".
add_hook_ref (bool, optional): Indicates whether to add a hook reference to the recorded data. Defaults to False.
**kwargs: Additional keyword arguments.
"""
super().__init__(name, env, **kwargs)
self.add_hook_ref: bool = add_hook_ref
"""Indicates whether to add a hook reference to the recorded data. Default value is False."""
log_path = log_path.replace("LOG_RECORD_NAME", name)
log_path = Path(expand_path(log_path, env_name=env.env_name))
self.log_path: Path = log_path
record_path = record_path.replace("LOG_RECORD_NAME", name)
record_path = Path(expand_path(record_path, env_name=env.env_name))
self.record_path: Path = record_path
"""The path to the log file. Default value is "USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl"."""
log.info(f"Recorder record for {name} in file://{log_path}")
os.makedirs(log_path.parent, exist_ok=True)
log.info(f"Recorder record for {name} in file://{record_path}")
os.makedirs(record_path.parent, exist_ok=True)
def __call__(self, hook_ref: str, env: Environment, **kwargs):
for key, item in kwargs.items():
......@@ -134,8 +127,8 @@ class FileRecorder(HookCallbackClass):
)
+ "\n"
)
with open(self.log_path, "a") as log_file:
log_file.write(record)
with open(self.record_path, "a") as record_file:
record_file.write(record)
except TypeError as e:
traceback.print_exception(e)
log.info(
......@@ -151,7 +144,7 @@ def print_recorded_events_human_readable(jsonl_path: Path):
"""
def stringify_item(item_):
def stringify_item(item_) -> str | None:
if isinstance(item_, float):
return str(item_)
if isinstance(item_, str):
......@@ -226,7 +219,5 @@ def print_recorded_events_human_readable(jsonl_path: Path):
if __name__ == "__main__":
json_lines_path: Path = Path(
"/home/fabian/.local/state/cooperative_cuisine/log/fcb095915c454446b9ee2905ff534610/game_events.jsonl"
)
json_lines_path: Path = Path(sys.argv[0])
print_recorded_events_human_readable(json_lines_path)
......@@ -98,86 +98,64 @@ effect_manager: { }
# fire_burns_ingredients_and_meals: true
extra_setup_functions:
hook_callbacks:
# # --------------- Scoring ---------------
orders:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ completed_order ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: 0.95
hooks: [ completed_order ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: 0.95
serve_not_ordered_meals:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ serve_not_ordered_meal ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: 0.95
hooks: [ serve_not_ordered_meal ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: 0.95
trashcan_usages:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ trashcan_usage ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: -0.2
hooks: [ trashcan_usage ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: -0.2
item_cut:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ cutting_board_100 ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: 0.1
hooks: [ cutting_board_100 ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: 0.1
stepped:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ post_step ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: -0.01
hooks: [ post_step ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: -0.01
combine:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ drop_off_on_cooking_equipment ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: 0.01
hooks: [ drop_off_on_cooking_equipment ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: 0.01
start_interact:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ player_start_interaction ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: 0.01
# json_states:
# func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
# kwargs:
# hooks: [ json_state ]
# log_class: !!python/name:cooperative_cuisine.recording.LogRecorder ''
# log_class_kwargs:
# log_path: USER_LOG_DIR/ENV_NAME/json_states.jsonl
hooks: [ player_start_interaction ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: 0.01
# json_states:
# hooks: [ json_state ]
# record_class: !!python/name:cooperative_cuisine.recording.LogRecorder ''
# record_class_kwargs:
# record_path: USER_LOG_DIR/ENV_NAME/json_states.jsonl
# actions:
# func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
# kwargs:
# hooks: [ pre_perform_action ]
# log_class: !!python/name:cooperative_cuisine.recording.LogRecorder ''
# log_class_kwargs:
# log_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
# hooks: [ pre_perform_action ]
# record_class: !!python/name:cooperative_cuisine.recording.LogRecorder ''
# record_class_kwargs:
# record_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
# random_env_events:
# func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
# kwargs:
# hooks: [ order_duration_sample, plate_out_of_kitchen_time ]
# log_class: !!python/name:cooperative_cuisine.recording.LogRecorder ''
# log_class_kwargs:
# log_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
# add_hook_ref: true
# hooks: [ order_duration_sample, plate_out_of_kitchen_time ]
# record_class: !!python/name:cooperative_cuisine.recording.LogRecorder ''
# record_class_kwargs:
# record_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
# add_hook_ref: true
# env_configs:
# func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
# kwargs:
# hooks: [ env_initialized, item_info_config ]
# log_class: !!python/name:cooperative_cuisine.recording.LogRecorder ''
# log_class_kwargs:
# log_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
# add_hook_ref: true
# hooks: [ env_initialized, item_info_config ]
# record_class: !!python/name:cooperative_cuisine.recording.LogRecorder ''
# record_class_kwargs:
# record_path: USER_LOG_DIR/ENV_NAME/LOG_RECORD_NAME.jsonl
# add_hook_ref: true
"""
Scores are managed via hooks. You can add them in the `environment_config` under `extra_setup_functions`.
Scores are managed via hooks. You can add them in the `environment_config` under `hook_callbacks`.
The here defined `ScoreViaHooks` is a `HookCallbackClass`. It allows you to define how the score is effected by
specific hook events.
......@@ -12,41 +12,33 @@ You can:
You can filter the events via `kwarg_filter`.
```yaml
extra_setup_functions:
hook_callbacks:
orders:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ completed_order ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: 20
score_on_specific_kwarg: meal_name
score_map:
Burger: 15
OnionSoup: 10
Salad: 5
TomatoSoup: 10
hooks: [ completed_order ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: 20
score_on_specific_kwarg: meal_name
score_map:
Burger: 15
OnionSoup: 10
Salad: 5
TomatoSoup: 10
not_ordered_meals:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ serve_not_ordered_meal ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: 2
hooks: [ serve_not_ordered_meal ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: 2
trashcan_usages:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ trashcan_usage ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: -5
hooks: [ trashcan_usage ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: -5
expired_orders:
func: !!python/name:cooperative_cuisine.hooks.hooks_via_callback_class ''
kwargs:
hooks: [ order_expired ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: -10
hooks: [ order_expired ]
callback_class: !!python/name:cooperative_cuisine.scores.ScoreViaHooks ''
callback_class_kwargs:
static_score: -10
```
......@@ -94,13 +86,13 @@ class ScoreViaHooks(HookCallbackClass):
**kwargs: Additional keyword arguments to be passed to the parent class.
"""
super().__init__(name, env, **kwargs)
self.score_map = score_map
self.score_map: dict[str, float] = score_map
"""Mapping of hook references to scores."""
self.static_score = static_score
self.static_score: float = static_score
"""The static score to be added if no other conditions are met."""
self.kwarg_filter = kwarg_filter
self.kwarg_filter: dict[str, Any] = kwarg_filter
"""Filtering condition for keyword arguments."""
self.score_on_specific_kwarg = score_on_specific_kwarg
self.score_on_specific_kwarg: str = score_on_specific_kwarg
"""The specific keyword argument to score on."""
def __call__(self, hook_ref: str, env: Environment, **kwargs):
......@@ -114,7 +106,7 @@ class ScoreViaHooks(HookCallbackClass):
self.env.increment_score(self.static_score, info=hook_ref)
elif self.score_map and hook_ref in self.score_map:
if self.kwarg_filter:
if kwargs.items() <= self.kwarg_filter.items():
if self.kwarg_filter.items() <= kwargs.items():
self.env.increment_score(
self.score_map[hook_ref],
info=f"{hook_ref} - {self.kwarg_filter}",
......
......@@ -282,3 +282,10 @@ def test_websocket_wrong_inputs(create_env_config):
finally:
task.cancel()
loop.close()
def test_root():
with TestClient(app) as client:
res = client.get("/")
assert res.status_code == status.HTTP_200_OK
assert res.json() == {"Cooperative": "Cuisine"}
import json
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.game_colors import RGB, WHITE, colors
def test_colors():
assert RGB(red=255, green=255, blue=255).hex_format() == "#FFFFFF"
assert WHITE.hex_format() == "#FFFFFF"
assert len(colors) >= 552
def test_calc_angle():
assert calc_angle([0.0, 1.0], [1.0, 0.0]) == -90.0
assert calc_angle([1.0, 1.0], [1.0, -1.0]) == -90.0
def test_drawing():
main([])
assert os.path.exists(os.path.join(ROOT_DIR, "generated", "screenshot.jpg"))
def test_visualizer():
with open(ROOT_DIR / "pygame_2d_vis" / "visualization.yaml", "r") as file:
visualization_config = yaml.safe_load(file)
vis = Visualizer(visualization_config)
vis.create_player_colors(10)
assert len(vis.player_colors) >= 10
assert len(set(vis.player_colors)) >= 10
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)
from collections import deque
from datetime import timedelta
import numpy as np
import pytest
import yaml
from cooperative_cuisine import ROOT_DIR
from cooperative_cuisine.action import ActionType, InterActionData, Action
from cooperative_cuisine.counters import Counter, CuttingBoard
from cooperative_cuisine.counters import (
Counter,
CuttingBoard,
CookingCounter,
ServingWindow,
Trashcan,
PlateDispenser,
Sink,
)
from cooperative_cuisine.effects import FireEffectManager
from cooperative_cuisine.environment import (
Environment,
)
from cooperative_cuisine.game_server import PlayerRequestType
from cooperative_cuisine.hooks import Hooks
from cooperative_cuisine.items import Item, ItemInfo, ItemType
from cooperative_cuisine.hooks import (
Hooks,
SERVE_NOT_ORDERED_MEAL,
PLAYER_ADDED,
POST_STEP,
)
from cooperative_cuisine.info_msg import InfoMsgManager
from cooperative_cuisine.items import Item, ItemInfo, ItemType, Plate, CookingEquipment
from cooperative_cuisine.scores import ScoreViaHooks
from cooperative_cuisine.server_results import (
PlayerInfo,
CreateEnvResult,
......@@ -21,7 +39,7 @@ from cooperative_cuisine.state_representation import (
StateRepresentation,
create_json_schema,
)
from cooperative_cuisine.utils import create_init_env_time
from cooperative_cuisine.utils import create_init_env_time, get_touching_counters
layouts_folder = ROOT_DIR / "configs" / "layouts"
environment_config_path = ROOT_DIR / "configs" / "environment_config.yaml"
......@@ -54,7 +72,6 @@ def layout_config():
with open(layout_path, "r") as file:
layout = file.read()
return layout
env.add_player("0")
@pytest.fixture
......@@ -218,6 +235,7 @@ def test_processing(env_config, layout_config, item_info):
},
)
env.counters.append(counter)
env.overwrite_counters(env.counters)
tomato = Item(name="Tomato", item_info=None)
env.add_player("1", np.array([2, 3]))
......@@ -308,3 +326,354 @@ def test_server_result_definition():
msg="123",
player_hash="1234324",
)
def test_fire(env_config, layout_config, item_info):
env = Environment(env_config, layout_config, item_info, as_files=False)
env.add_player("0")
oven = None
for c in env.counters:
if (
isinstance(c, CookingCounter)
and c.name == "Stove"
and c.occupied_by.name == "Pan"
):
oven = c
break
assert oven is not None
raw_patty = Item(name="RawPatty", item_info=env.item_info["RawPatty"])
assert oven.can_drop_off(raw_patty)
oven.drop_off(raw_patty, "0")
assert isinstance(oven.occupied_by, CookingEquipment)
assert oven.occupied_by.content_list == [raw_patty]
env.step(timedelta(seconds=env.item_info["CookedPatty"].seconds))
assert oven.occupied_by.content_list[0].name == "CookedPatty"
env.step(timedelta(seconds=env.item_info["BurntCookedPatty"].seconds))
assert oven.occupied_by.content_list[0].name == "BurntCookedPatty"
env.step(timedelta(seconds=env.item_info["Fire"].seconds))
assert len(oven.occupied_by.active_effects) != 0
assert oven.occupied_by.active_effects[0].name == "Fire"
fire_manager = env.effect_manager["FireManager"]
assert isinstance(fire_manager, FireEffectManager)
env.step(fire_manager.next_finished_timer - env.env_time)
touching_counters = get_touching_counters(oven, env.counters)
next_empty = None
connect_counter = None
for c in touching_counters:
if c.occupied_by:
assert len(c.occupied_by.active_effects) == 1
else:
assert len(c.active_effects) == 1
next_touching = get_touching_counters(c, env.counters)
for a in next_touching:
if a not in touching_counters and a.__class__.__name__ == "Counter":
a.occupied_by = None
next_empty = a
connect_counter = c
env.step(timedelta(seconds=0.01))
assert next_empty is not None
next_empty.occupied_by = Item(name="Tomato", item_info=env.item_info["Tomato"])
env.step(
fire_manager.effect_to_timer[connect_counter.active_effects[0].uuid]
- env.env_time
)
assert len(next_empty.occupied_by.active_effects) == 1
fire_extinguisher = None
for c in env.counters:
if c.occupied_by and c.occupied_by.name == "Extinguisher":
fire_extinguisher = c.occupied_by
c.occupied_by = None
break
assert fire_extinguisher is not None
env.players["0"].holding = fire_extinguisher
env.players["0"].pos = oven.pos
env.players["0"].pos[1] += 1.0
env.perform_action(
Action(
player="0",
action_type=ActionType.MOVEMENT,
action_data=np.array([0.0, -1.0]),
duration=0.1,
)
)
env.step(timedelta(seconds=0.1))
env.perform_action(
Action(
player="0",
action_type=ActionType.INTERACT,
action_data=InterActionData.START,
)
)
env.step(timedelta(seconds=env.item_info["Extinguisher"].seconds))
env.step(timedelta(seconds=env.item_info["Extinguisher"].seconds))
assert len(oven.occupied_by.active_effects) == 0
def test_score(env_config, layout_config, item_info):
def incr_score_callback(hook_ref, env: Environment, meal, meal_name, **kwargs):
assert isinstance(meal, Item)
assert isinstance(meal_name, str)
assert meal_name == "TomatoSoup"
env.increment_score(1_000, "Soup Soup")
env = Environment(env_config, layout_config, item_info, as_files=False)
assert env.score == 0.0
env.add_player("0")
env.register_callback_for_hook(SERVE_NOT_ORDERED_MEAL, incr_score_callback)
env.register_callback_for_hook(
SERVE_NOT_ORDERED_MEAL,
ScoreViaHooks(
name="123",
env=env,
score_on_specific_kwarg="meal_name",
score_map={"TomatoSoup": 2_000},
),
)
env.register_callback_for_hook(
SERVE_NOT_ORDERED_MEAL,
ScoreViaHooks(name="124", env=env, score_map={SERVE_NOT_ORDERED_MEAL: 4_000}),
)
env.register_callback_for_hook(
SERVE_NOT_ORDERED_MEAL,
ScoreViaHooks(
name="124",
env=env,
score_map={SERVE_NOT_ORDERED_MEAL: 8_000},
kwarg_filter={"meal_name": "TomatoSoup"},
),
)
env.register_callback_for_hook(
SERVE_NOT_ORDERED_MEAL,
ScoreViaHooks(
name="123",
env=env,
score_on_specific_kwarg="meal_name",
static_score=16_000,
score_map={},
),
)
serving_window = None
for c in env.counters:
if isinstance(c, ServingWindow):
serving_window = c
break
assert serving_window is not None
env.order_manager.serving_not_ordered_meals = True
env.order_manager.open_orders = []
plate = Plate(
transitions=env.counter_factory.filter_item_info(
by_item_type=ItemType.Meal, add_effects=True
),
clean=True,
item_info=env.item_info["Plate"],
hook=env.hook,
)
plate.content_list = [
Item(name="TomatoSoup", item_info=env.item_info["TomatoSoup"])
]
assert serving_window.can_drop_off(plate)
returned = serving_window.drop_off(plate, "0")
assert returned is None
plates_prev = len(serving_window.plate_dispenser.occupied_by)
assert env.score >= 31_000
assert len(serving_window.plate_dispenser.out_of_kitchen_timer) == 1
env.step(serving_window.plate_dispenser.out_of_kitchen_timer[0] - env.env_time)
assert len(serving_window.plate_dispenser.out_of_kitchen_timer) == 0
assert len(serving_window.plate_dispenser.occupied_by) == plates_prev + 1
assert (
serving_window.plate_dispenser.occupied_by[0].clean
!= serving_window.plate_dispenser.plate_config.return_dirty
)
def test_info_msgs(env_config, layout_config, item_info):
env_config_dict = yaml.load(env_config, Loader=yaml.Loader)
# TODO change after merge with 115
env_config_dict["hook_callbacks"]["dummy_msg"] = {
"hooks": [PLAYER_ADDED],
"callback_class": InfoMsgManager,
"callback_class_kwargs": {"msg": "hello there"},
}
env_config_dict["hook_callbacks"]["dummy_msg_2"] = {
"hooks": [POST_STEP],
"callback_class": InfoMsgManager,
"callback_class_kwargs": {"msg": "step step"},
}
env_config = yaml.dump(env_config_dict)
env = Environment(env_config, layout_config, item_info, as_files=False)
env.add_player("0")
assert env.info_msgs_per_player["0"][0]["msg"] == "hello there"
env.step(timedelta(seconds=0.1))
assert env.info_msgs_per_player["0"][1]["msg"] == "step step"
env.step(env.info_msgs_per_player["0"][0]["end_time"] - env.env_time)
assert len(env.info_msgs_per_player["0"]) == 2
assert env.info_msgs_per_player["0"][0]["msg"] == "step step"
def test_trashcan(env_config, layout_config, item_info):
env = Environment(env_config, layout_config, item_info, as_files=False)
env.add_player("0")
trash = None
for c in env.counters:
if isinstance(c, Trashcan):
trash = c
break
assert trash is not None
item = Item(name="Tomato", item_info=env.item_info["Tomato"])
assert trash.can_drop_off(item)
assert trash.drop_off(item, "0") is None
plate = Plate(
transitions=env.counter_factory.filter_item_info(
by_item_type=ItemType.Meal, add_effects=True
),
clean=True,
item_info=env.item_info["Plate"],
hook=env.hook,
)
plate.content_list = [
Item(name="TomatoSoup", item_info=env.item_info["TomatoSoup"])
]
assert trash.can_drop_off(plate)
assert trash.drop_off(plate, "0") == plate
assert plate.content_list == []
assert trash.pick_up(True, "0") is None
def test_plate_dispenser(env_config, layout_config, item_info):
env = Environment(env_config, layout_config, item_info, as_files=False)
env.add_player("0")
plate_dis = None
for c in env.counters:
if isinstance(c, PlateDispenser):
plate_dis = c
break
assert plate_dis is not None
assert (
len(plate_dis.occupied_by) > 0
) # Otherwise adapt env_config above before passing to Environment
n_plates = len(plate_dis.occupied_by)
env = Environment(env_config, layout_config, item_info, as_files=False)
env.add_player("0")
item = Item(name="ChoppedTomato", item_info=env.item_info["ChoppedTomato"])
assert plate_dis.can_drop_off(item)
returned = plate_dis.drop_off(item, "0")
assert returned is None
assert len(plate_dis.occupied_by) == n_plates
first_plate = plate_dis.pick_up(True, "0")
assert isinstance(first_plate, Plate)
assert (
first_plate.content_list and first_plate.content_list[0].name == "ChoppedTomato"
)
assert plate_dis.can_drop_off(first_plate)
returned = plate_dis.drop_off(first_plate, "0")
assert isinstance(returned, Plate) and len(returned.content_list) == 0
assert plate_dis.occupied_by[-1].content_list[0].name == "ChoppedTomato"
plate_dis.occupied_by = deque()
assert plate_dis.can_drop_off(item)
returned = plate_dis.drop_off(item, "0")
assert returned is None
assert plate_dis.occupied_by[0].name == "ChoppedTomato"
def test_sink(env_config, layout_config, item_info):
env = Environment(env_config, layout_config, item_info, as_files=False)
env.add_player("0")
sink = None
for c in env.counters:
if isinstance(c, Sink):
sink = c
break
assert sink is not None
env.players["0"].pos = sink.pos
env.players["0"].pos[1] -= 1.0
env.perform_action(
Action(
player="0",
action_type=ActionType.MOVEMENT,
action_data=np.array([0.0, 1.0]),
duration=0.1,
)
)
env.step(timedelta(seconds=0.1))
plate = Plate(
transitions=env.counter_factory.filter_item_info(
by_item_type=ItemType.Meal, add_effects=True
),
clean=False,
item_info=env.item_info["Plate"],
hook=env.hook,
)
plate_2 = Plate(
transitions=env.counter_factory.filter_item_info(
by_item_type=ItemType.Meal, add_effects=True
),
clean=False,
item_info=env.item_info["Plate"],
hook=env.hook,
)
clean_plate = Plate(
transitions=env.counter_factory.filter_item_info(
by_item_type=ItemType.Meal, add_effects=True
),
clean=True,
item_info=env.item_info["Plate"],
hook=env.hook,
)
assert sink.can_drop_off(plate)
assert sink.drop_off(plate, "0") is None
assert sink.can_drop_off(plate_2)
assert sink.drop_off(plate_2, "0") is None
assert not sink.can_drop_off(clean_plate)
assert len(sink.occupied_by) == 2
env.perform_action(
Action(
player="0",
action_type=ActionType.INTERACT,
action_data=InterActionData.START,
)
)
env.step(timedelta(seconds=env.item_info["Plate"].seconds))
assert len(sink.occupied_by) == 1
assert len(sink.sink_addon.occupied_by) == 1
assert sink.sink_addon.occupied_by[0].clean
assert not sink.occupied_by[0].clean
assert sink.pick_up(True, "0") is None
env.step(timedelta(seconds=env.item_info["Plate"].seconds))
assert len(sink.occupied_by) == 0
assert len(sink.sink_addon.occupied_by) == 2
assert sink.sink_addon.occupied_by[0].clean
assert sink.sink_addon.occupied_by[1].clean
item = Item(name="ChoppedTomato", item_info=env.item_info["ChoppedTomato"])
assert sink.sink_addon.can_drop_off(item)
assert sink.sink_addon.drop_off(item, "0") is None
assert sink.sink_addon.pick_up(True, "0").content_list[0].name == "ChoppedTomato"
assert len(sink.sink_addon.occupied_by) == 1
......@@ -92,4 +92,40 @@ def test_game_server_crashed():
assert res.status_code == status.HTTP_500_INTERNAL_SERVER_ERROR
def test_tutorial():
test_response = Response()
test_response.status_code = status.HTTP_200_OK
test_response.encoding = "utf8"
test_response._content = json.dumps(
{
"player_info": {
"0": {
"player_id": "0",
"client_id": "ksjdhfkjsdfn",
"player_hash": "shdfbmsndfb",
}
},
"env_id": "123456789",
"recipe_graphs": [],
}
).encode()
with mock.patch.object(
study_server_module, "request_game_server", return_value=test_response
) as mock_call:
with TestClient(app) as client:
res = client.post("/connect_to_tutorial/124")
assert res.status_code == status.HTTP_200_OK
mock_call.assert_called_once()
with mock.patch.object(
study_server_module, "request_game_server", return_value=test_response
) as mock_call:
with TestClient(app) as client:
res = client.post("/disconnect_from_tutorial/124")
assert res.status_code == status.HTTP_200_OK
# TOOD test bots