{"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_datetime, is_int_value, overlaps\n\ndef run(payload, policy):\n    tz = ZoneInfo(policy['timezone'])\n    cutoff_hour = policy['cutoff_hour']\n    cutoff_inclusive = policy['cutoff_inclusive']\n    lead_minutes = policy['lead_minutes']\n    duration_max = policy['duration_max']\n    duplicate_policy = policy['duplicate_policy']\n    cancelled_blocks = policy['cancelled_blocks']\n    priority_high_first = policy['priority_high_first']\n    capacity = policy['capacity']\n    adjacency_allowed = policy['adjacency_allowed']\n    blackout_day = policy['blackout_day']\n    report_order = policy['report_order']\n    selected = []\n    blocked = []\n    rejected = []\n    accepted = []\n    raw = []\n    now_dt = None\n    if isinstance(payload, dict):\n        now_dt = parse_datetime(payload.get('now'))\n        appts = payload.get('appointments')\n        if isinstance(appts, list):\n            raw = list(appts)\n    retained = {}\n    order = []\n    for idx, item in enumerate(raw):\n        if not isinstance(item, dict):\n            continue\n        appt_id = item.get('id')\n        if not isinstance(appt_id, str):\n            rejected.append((idx, appt_id))\n            continue\n        if appt_id not in retained:\n            retained[appt_id] = (idx, item)\n            order.append(appt_id)\n        elif duplicate_policy == 'last':\n            retained[appt_id] = (idx, item)\n    candidates = []\n    for appt_id in order:\n        idx, item = retained[appt_id]\n        if now_dt is None or now_dt.tzinfo is None or now_dt.utcoffset() is None:\n            rejected.append((idx, appt_id))\n            continue\n        start_dt = parse_datetime(item.get('start'))\n        duration = item.get('duration', item.get('duration_minutes'))\n        priority = item.get('priority')\n        cancelled = item.get('cancelled', False)\n        valid = True\n        if start_dt is None or start_dt.tzinfo is None or start_dt.utcoffset() is None:\n            valid = False\n        if isinstance(duration, bool) or not isinstance(duration, (int, float)):\n            valid = False\n        elif isinstance(duration, float) and (duration != duration or duration in (float('inf'), float('-inf'))):\n            valid = False\n        if not is_int_value(priority):\n            valid = False\n        if not isinstance(cancelled, bool):\n            valid = False\n        if not valid:\n            rejected.append((idx, appt_id))\n            continue\n        if not (duration > 0 and duration <= duration_max):\n            rejected.append((idx, appt_id))\n            continue\n        start_utc = start_dt.astimezone(timezone.utc)\n        end_utc = start_utc + timedelta(minutes=duration)\n        if start_utc < now_dt.astimezone(timezone.utc) + timedelta(minutes=lead_minutes):\n            rejected.append((idx, appt_id))\n            continue\n        start_local = start_utc.astimezone(tz)\n        if start_local.date().isoformat() == blackout_day:\n            rejected.append((idx, appt_id))\n            continue\n        cutoff_local = datetime(start_local.year, start_local.month, start_local.day, cutoff_hour, 0, tzinfo=tz)\n        if cutoff_inclusive:\n            if not (end_utc <= cutoff_local):\n                rejected.append((idx, appt_id))\n                continue\n        else:\n            if not (end_utc < cutoff_local):\n                rejected.append((idx, appt_id))\n                continue\n        if cancelled and not cancelled_blocks:\n            rejected.append((idx, appt_id))\n            continue\n        candidates.append({'id': appt_id, 'index': idx, 'priority': priority, 'cancelled': cancelled, 'start': start_utc, 'end': end_utc})\n    if priority_high_first:\n        candidates.sort(key=lambda c: (-c['priority'], c['index']))\n    else:\n        candidates.sort(key=lambda c: (c['priority'], c['index']))\n    for cand in candidates:\n        count = 0\n        for other in accepted:\n            if overlaps(cand['start'], cand['end'], other['start'], other['end'], adjacency_allowed):\n                count += 1\n        if count < capacity:\n            accepted.append(cand)\n            if cand['cancelled']:\n                blocked.append((cand['index'], cand['id']))\n            else:\n                selected.append((cand['index'], cand['id']))\n        else:\n            rejected.append((cand['index'], cand['id']))\n    def finish(entries):\n        if report_order == 'id':\n            entries_sorted = sorted(entries, key=lambda e: str(e[1]))\n        else:\n            entries_sorted = sorted(entries, key=lambda e: e[0])\n        return [e[1] for e in entries_sorted]\n    return {'selected': finish(selected), 'blocked': finish(blocked), 'rejected': finish(rejected)}\n", "policy.py": "POLICY = {'timezone': 'America/New_York', 'cutoff_hour': 17, 'cutoff_inclusive': True, 'lead_minutes': 30, 'adjacency_allowed': True, 'cancelled_blocks': True, 'duplicate_policy': 'first', 'duration_max': 120, 'capacity': 1, 'report_order': 'id', 'blackout_day': '2026-11-01', 'priority_high_first': True}\n", "helpers.py": "from datetime import datetime\n\ndef parse_datetime(value):\n    if isinstance(value, datetime):\n        return 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        return datetime.fromisoformat(text)\n    except ValueError:\n        return None\n\ndef is_int_value(value):\n    return isinstance(value, int) and not isinstance(value, bool)\n\ndef overlaps(s1, e1, s2, e2, adjacency_allowed):\n    if adjacency_allowed:\n        return s1 < e2 and s2 < e1\n    return s1 <= e2 and s2 <= e1\n"}}