{"files": {"main.py": "from core import run\nfrom policy import POLICY\ndef evaluate(payload):\n    return run(payload, POLICY)\n", "core.py": "from datetime import datetime, timedelta, timezone\nfrom zoneinfo import ZoneInfo\nfrom helpers import parse_aware_datetime, intervals_overlap\n\ndef run(payload, policy):\n    selected = []\n    blocked = []\n    rejected = []\n    if not isinstance(payload, dict):\n        return {\"selected\": selected, \"blocked\": blocked, \"rejected\": rejected}\n    appointments = payload.get(\"appointments\")\n    if not isinstance(appointments, list):\n        return {\"selected\": selected, \"blocked\": blocked, \"rejected\": rejected}\n    duplicate_policy = policy.get(\"duplicate_policy\", \"first\")\n    retained = {}\n    for original_index, appointment in enumerate(appointments):\n        if not isinstance(appointment, dict):\n            continue\n        appointment_id = appointment.get(\"id\")\n        if not isinstance(appointment_id, str):\n            continue\n        if appointment_id not in retained:\n            retained[appointment_id] = (original_index, appointment)\n        elif duplicate_policy == \"last\":\n            retained[appointment_id] = (original_index, appointment)\n    index_by_id = {appointment_id: value[0] for appointment_id, value in retained.items()}\n    def sort_output(ids):\n        if policy.get(\"report_order\") == \"id\":\n            return sorted(ids)\n        return sorted(ids, key=lambda appointment_id: index_by_id.get(appointment_id, 0))\n    now = parse_aware_datetime(payload.get(\"now\"))\n    if now is None:\n        rejected = list(retained.keys())\n        return {\"selected\": [], \"blocked\": [], \"rejected\": sort_output(rejected)}\n    try:\n        local_zone = ZoneInfo(policy.get(\"timezone\", \"UTC\"))\n    except Exception:\n        local_zone = timezone.utc\n    now_utc = now.astimezone(timezone.utc)\n    earliest_start = now_utc + timedelta(minutes=policy.get(\"lead_minutes\", 0))\n    duration_max = policy.get(\"duration_max\")\n    blackout_day = policy.get(\"blackout_day\")\n    cutoff_hour = policy.get(\"cutoff_hour\", 23)\n    cutoff_inclusive = policy.get(\"cutoff_inclusive\", True)\n    cancelled_blocks = policy.get(\"cancelled_blocks\", False)\n    capacity = policy.get(\"capacity\", 1)\n    adjacency_allowed = policy.get(\"adjacency_allowed\", True)\n    priority_high_first = policy.get(\"priority_high_first\", True)\n    candidates = []\n    for appointment_id, (original_index, appointment) in retained.items():\n        duration = appointment.get(\"duration\")\n        priority = appointment.get(\"priority\")\n        cancelled = appointment.get(\"cancelled\")\n        start = parse_aware_datetime(appointment.get(\"start\"))\n        if isinstance(duration, bool) or not isinstance(duration, int):\n            rejected.append(appointment_id)\n            continue\n        if isinstance(priority, bool) or not isinstance(priority, int):\n            rejected.append(appointment_id)\n            continue\n        if not isinstance(cancelled, bool):\n            rejected.append(appointment_id)\n            continue\n        if start is None:\n            rejected.append(appointment_id)\n            continue\n        if duration <= 0 or (duration_max is not None and duration > duration_max):\n            rejected.append(appointment_id)\n            continue\n        start_utc = start.astimezone(timezone.utc)\n        end_utc = start_utc + timedelta(minutes=duration)\n        if start_utc < earliest_start:\n            rejected.append(appointment_id)\n            continue\n        start_local = start_utc.astimezone(local_zone)\n        if blackout_day is not None and start_local.date().isoformat() == str(blackout_day):\n            rejected.append(appointment_id)\n            continue\n        cutoff_local = datetime(start_local.year, start_local.month, start_local.day, int(cutoff_hour), 0, tzinfo=local_zone)\n        cutoff_utc = cutoff_local.astimezone(timezone.utc)\n        if cutoff_inclusive:\n            if end_utc > cutoff_utc:\n                rejected.append(appointment_id)\n                continue\n        else:\n            if end_utc >= cutoff_utc:\n                rejected.append(appointment_id)\n                continue\n        if cancelled and not cancelled_blocks:\n            rejected.append(appointment_id)\n            continue\n        candidates.append({\"id\": appointment_id, \"index\": original_index, \"priority\": priority, \"cancelled\": cancelled, \"start\": start_utc, \"end\": end_utc})\n    if priority_high_first:\n        candidates.sort(key=lambda item: (-item[\"priority\"], item[\"index\"]))\n    else:\n        candidates.sort(key=lambda item: (item[\"priority\"], item[\"index\"]))\n    accepted_intervals = []\n    for candidate in candidates:\n        overlap_count = 0\n        for accepted_start, accepted_end in accepted_intervals:\n            if intervals_overlap(candidate[\"start\"], candidate[\"end\"], accepted_start, accepted_end, adjacency_allowed):\n                overlap_count += 1\n        if overlap_count < capacity:\n            accepted_intervals.append((candidate[\"start\"], candidate[\"end\"]))\n            if candidate[\"cancelled\"]:\n                blocked.append(candidate[\"id\"])\n            else:\n                selected.append(candidate[\"id\"])\n        else:\n            rejected.append(candidate[\"id\"])\n    return {\"selected\": sort_output(selected), \"blocked\": sort_output(blocked), \"rejected\": sort_output(rejected)}\n", "policy.py": "POLICY = {\"adjacency_allowed\": True, \"blackout_day\": \"2026-11-01\", \"cancelled_blocks\": True, \"capacity\": 1, \"cutoff_hour\": 17, \"cutoff_inclusive\": True, \"duplicate_policy\": \"first\", \"duration_max\": 120, \"lead_minutes\": 30, \"priority_high_first\": True, \"report_order\": \"id\", \"timezone\": \"America/New_York\"}\n", "helpers.py": "from datetime import datetime\n\ndef parse_aware_datetime(value):\n    if not isinstance(value, str):\n        return None\n    text = value.strip()\n    if text.endswith((\"Z\", \"z\")):\n        text = text[:-1] + \"+00:00\"\n    try:\n        parsed = datetime.fromisoformat(text)\n    except ValueError:\n        return None\n    if parsed.tzinfo is None or parsed.utcoffset() is None:\n        return None\n    return parsed\n\ndef intervals_overlap(first_start, first_end, second_start, second_end, adjacency_allowed):\n    if adjacency_allowed:\n        return first_start < second_end and second_start < first_end\n    return first_start <= second_end and second_start <= first_end\n"}}