from typing import Literal, TypedDict, List Priority = Literal["low", "normal", "high"] class Errand(TypedDict): errand_id: str priority: Priority day_part: str # morning, afternoon, evening requires_human: bool class ErrandDecision(TypedDict): errand_id: str scheduled_day_part: str reason: str def schedule_errands(errands: List[Errand], max_per_part: int = 3) -> List[ErrandDecision]: """Very small heuristic scheduler that spreads errands across the day. - High priority errands are kept in their requested `day_part`. - Normal/low priority errands may be shifted to less busy parts of day. """ decisions: List[ErrandDecision] = [] def pick_slot(preferred: str) -> str: # Simple fallback order order_slots = [preferred, "morning", "afternoon", "evening"] for slot in order_slots: if len([d for d in decisions if d["scheduled_day_part"] == slot]) < max_per_part: return slot return preferred # Priority order order = {"high": 0, "normal": 1, "low": 2} all_errands = sorted(errands, key=lambda e: order.get(e["priority"], 1)) for e in all_errands: preferred = e["day_part"] slot = pick_slot(preferred) reason = f"Scheduled in {slot}; priority={e['priority']}." if slot != preferred: reason += f" Shifted from preferred {preferred} to balance load." decisions.append( { "errand_id": e["errand_id"], "scheduled_day_part": slot, "reason": reason, } ) return decisions if __name__ == "__main__": sample: List[Errand] = [ {"errand_id": "ER_GROCERY", "priority": "high", "day_part": "morning", "requires_human": True}, {"errand_id": "ER_TRASH", "priority": "high", "day_part": "evening", "requires_human": True}, {"errand_id": "ER_PET_FOOD", "priority": "high", "day_part": "afternoon", "requires_human": True}, {"errand_id": "ER_DONATION", "priority": "low", "day_part": "morning", "requires_human": True}, ] for d in schedule_errands(sample): print(d)