Spaces:
Sleeping
Sleeping
| from __future__ import annotations | |
| import argparse | |
| from typing import Tuple | |
| import numpy as np | |
| from focus_resource_env import ( | |
| DEEP_WORK, | |
| EMPTY, | |
| MEETING, | |
| OP_IDLE, | |
| OP_MUTE_COMMS, | |
| OP_RESCHEDULE_MEETING, | |
| OP_SCHEDULE_WORK, | |
| FocusResourceEnv, | |
| ) | |
| def choose_action(env: FocusResourceEnv) -> Tuple[int, int]: | |
| current = env.current_slot | |
| if env.current_slot == 0 and not env.mute_comms and env.distraction_risk > 0.0: | |
| return current, OP_MUTE_COMMS | |
| if env.recovery_remaining > 0: | |
| return current, OP_IDLE | |
| if current < env.timeline_length and env.timeline[current] == EMPTY: | |
| return current, OP_SCHEDULE_WORK | |
| empty_slots = np.where(env.timeline[current:] == EMPTY)[0] | |
| if empty_slots.size > 0: | |
| target = current + int(empty_slots[0]) | |
| return target, OP_SCHEDULE_WORK | |
| fragmented_meetings = future_meeting_starts(env, current) | |
| if fragmented_meetings: | |
| _, largest_empty_len = largest_empty_block(env.timeline, current) | |
| if largest_empty_len < 8: | |
| return fragmented_meetings[0], OP_RESCHEDULE_MEETING | |
| return current, OP_IDLE | |
| def largest_empty_block(timeline: np.ndarray, start_index: int) -> Tuple[int, int]: | |
| best_start = start_index | |
| best_len = 0 | |
| idx = start_index | |
| while idx < len(timeline): | |
| if timeline[idx] != EMPTY: | |
| idx += 1 | |
| continue | |
| run_start = idx | |
| while idx < len(timeline) and timeline[idx] == EMPTY: | |
| idx += 1 | |
| run_len = idx - run_start | |
| if run_len > best_len: | |
| best_start = run_start | |
| best_len = run_len | |
| return best_start, best_len | |
| def future_meeting_starts(env: FocusResourceEnv, current: int) -> list[int]: | |
| starts = [] | |
| seen = set() | |
| for slot in range(current, env.timeline_length): | |
| if env.timeline[slot] != MEETING: | |
| continue | |
| meta = env.meeting_meta.get(slot) | |
| if meta is None: | |
| continue | |
| start = meta["start"] | |
| if start in seen or start < current: | |
| continue | |
| seen.add(start) | |
| starts.append(start) | |
| return starts | |
| def main() -> None: | |
| parser = argparse.ArgumentParser(description="Run the FocusResourceEnv simulation.") | |
| parser.add_argument("--start-hour", default="09:00") | |
| parser.add_argument("--end-hour", default="17:00") | |
| parser.add_argument("--distraction-risk", type=float, default=0.15) | |
| parser.add_argument("--seed", type=int, default=7) | |
| args = parser.parse_args() | |
| env = FocusResourceEnv( | |
| start_hour=args.start_hour, | |
| end_hour=args.end_hour, | |
| distraction_risk=args.distraction_risk, | |
| seed=args.seed, | |
| ) | |
| observation = env.reset() | |
| total_reward = 0.0 | |
| print("Initial observation:") | |
| print(observation) | |
| print(env.render_text()) | |
| done = False | |
| while not done: | |
| action = choose_action(env) | |
| observation, reward, done, info = env.step(action) | |
| total_reward += reward | |
| print(f"action={action} reward={reward:.2f}") | |
| print(info) | |
| print(env.render_text()) | |
| print("\nFinal Flow Efficiency score") | |
| print(f"episode_reward={total_reward:.2f}") | |
| print(f"flow_score={env.flow_score:.2f}") | |
| print(f"social_debt={env.social_debt:.2f}") | |
| print(f"calendar_churn={env.calendar_churn}") | |
| print(f"interruptions={env.interruptions}") | |
| print(f"invalid_actions={env.invalid_actions}") | |
| if __name__ == "__main__": | |
| main() | |