""" Simulation runner — executes a complete shift episode. This is the main entry point for running the environment: result, grade_report = run_episode("weekday_lunch", policy_fn) """ from __future__ import annotations from typing import Callable from env.environment import RestaurantEnv from env.graders import grade from env.models import AgentAction, RestaurantState, ShiftResult def run_episode( task_id: str, policy: Callable[[RestaurantState], AgentAction], verbose: bool = False, ) -> tuple[ShiftResult, dict]: """ Run a complete shift from start to finish. Args: task_id: which task to run ("weekday_lunch", "weekend_rush", "crisis_shift") policy: a function that takes RestaurantState and returns AgentAction verbose: if True, print step-by-step info Returns: (result, grade_report) where: - result: ShiftResult with final metrics - grade_report: dict with final_score and pillar breakdowns """ env = RestaurantEnv() state = env.reset(task_id) if verbose: print(f"\n{'='*60}") print(f" Task: {task_id}") print(f" Shift start: {state.time_of_day}") active = [s.name for s in state.staff if s.is_active] print(f" Active staff: {', '.join(active)}") print(f" Rating: {state.customer_rating} | Demand: {state.demand_level}x") print(f"{'='*60}\n") done = False total_reward = 0.0 while not done: action = policy(state) state, reward, done, info = env.step(action) total_reward += reward if verbose: print( f" Step {info['step']:2d} | {state.time_of_day} | " f"customers={info['customers_arrived']:2d} | " f"served={info['orders_served']:2d} failed={info['orders_failed']:2d} | " f"profit={info['step_profit']:+8.0f} | " f"rating={state.customer_rating:.2f} | " f"reward={reward:+.3f}" ) if info.get("events"): for event in info["events"]: print(f" ↳ {event}") result = env.get_result() grade_report = grade(task_id, result) if verbose: print(f"\n{'─'*60}") print(f" SHIFT COMPLETE") print(f" Revenue: {result.total_revenue:,.0f}") print(f" Costs: {result.total_costs:,.0f}") print(f" Profit: {result.profit:,.0f}") print(f" Rating: {result.average_rating:.2f}") print(f" Served/Failed:{result.orders_served}/{result.orders_failed}") print(f" Satisfaction: {result.customer_satisfaction:.1f}/100") print(f" Total Reward: {total_reward:.3f}") print(f" FINAL SCORE: {grade_report['final_score']}/100") print(f"{'─'*60}\n") return result, grade_report