engineer-manager / run_sim.py
AzraelH's picture
First commit
9fe417b
Raw
History Blame Contribute Delete
3.51 kB
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()