{"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, as_int\n\ndef run(payload, policy):\n    policy = dict(policy) if isinstance(policy, dict) else {}\n    defaults = {\n        'adjacency_allowed': True,\n        'blackout_day': '2026-11-01',\n        'cancelled_blocks': True,\n        'capacity': 1,\n        'cutoff_hour': 17,\n        'cutoff_inclusive': True,\n        'duplicate_policy': 'first',\n        'duration_max': 120,\n        'lead_minutes': 30,\n        'priority_high_first': True,\n        'report_order': 'id',\n        'timezone': 'America/New_York',\n    }\n    cfg = dict(defaults)\n    cfg.update(policy)\n    selected = []\n    blocked = []\n    rejected = []\n    if not isinstance(payload, dict):\n        return {'selected': [], 'blocked': [], 'rejected': []}\n    appointments = payload.get('appointments')\n    if not isinstance(appointments, list):\n        return {'selected': [], 'blocked': [], 'rejected': []}\n    now_dt = parse_aware(payload.get('now'))\n    try:\n        tz = ZoneInfo(str(cfg.get('timezone')))\n    except Exception:\n        tz = timezone.utc\n    duration_max = as_int(cfg.get('duration_max'))\n    lead_minutes = as_int(cfg.get('lead_minutes'))\n    if lead_minutes is None:\n        lead_minutes = 0\n    capacity = as_int(cfg.get('capacity'))\n    if capacity is None:\n        capacity = 0\n    cutoff_hour = as_int(cfg.get('cutoff_hour'))\n    duplicate_policy = cfg.get('duplicate_policy')\n    deduped = {}\n    order_keys = []\n    for idx, item in enumerate(appointments):\n        if not isinstance(item, dict):\n            continue\n        appt_id = item.get('id')\n        if appt_id is None or isinstance(appt_id, bool) or not isinstance(appt_id, (str, int)):\n            continue\n        if isinstance(appt_id, str) and appt_id == '':\n            continue\n        try:\n            exists = appt_id in deduped\n        except Exception:\n            continue\n        if not exists:\n            deduped[appt_id] = (idx, item)\n            order_keys.append(appt_id)\n        elif duplicate_policy == 'last':\n            deduped[appt_id] = (idx, item)\n    entries = [(deduped[k][0], deduped[k][1]) for k in order_keys]\n    candidates = []\n    for orig_idx, item in entries:\n        appt_id = item.get('id')\n        start_dt = parse_aware(item.get('start'))\n        duration = as_int(item.get('duration'))\n        if 'duration' in item and isinstance(item.get('duration'), float) and not item.get('duration').is_integer():\n            duration = None\n        priority = as_int(item.get('priority'))\n        cancelled = item.get('cancelled', False)\n        valid = True\n        if now_dt is None or start_dt is None:\n            valid = False\n        if duration is None or duration_max is None or duration <= 0 or duration > duration_max:\n            valid = False\n        if priority is None:\n            valid = False\n        if not isinstance(cancelled, bool):\n            valid = False\n            cancelled = False\n        if cutoff_hour is None or cutoff_hour < 0 or cutoff_hour > 23:\n            valid = False\n        if not valid:\n            rejected.append((appt_id, orig_idx))\n            continue\n        start_utc = start_dt.astimezone(timezone.utc)\n        end_utc = start_utc + timedelta(minutes=duration)\n        earliest = now_dt.astimezone(timezone.utc) + timedelta(minutes=lead_minutes)\n        if start_utc < earliest:\n            rejected.append((appt_id, orig_idx))\n            continue\n        local_start = start_utc.astimezone(tz)\n        blackout = cfg.get('blackout_day')\n        if blackout is not None and local_start.date().isoformat() == str(blackout):\n            rejected.append((appt_id, orig_idx))\n            continue\n        cutoff_dt = datetime(local_start.year, local_start.month, local_start.day, hour=cutoff_hour, minute=0, second=0, tzinfo=tz)\n        if cfg.get('cutoff_inclusive'):\n            if not (end_utc <= cutoff_dt):\n                rejected.append((appt_id, orig_idx))\n                continue\n        else:\n            if not (end_utc < cutoff_dt):\n                rejected.append((appt_id, orig_idx))\n                continue\n        if cancelled and not cfg.get('cancelled_blocks'):\n            rejected.append((appt_id, orig_idx))\n            continue\n        candidates.append({'id': appt_id, 'index': orig_idx, 'priority': priority, 'cancelled': cancelled, 'start': start_utc, 'end': end_utc})\n    if cfg.get('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    accepted = []\n    adjacency = bool(cfg.get('adjacency_allowed'))\n    for cand in candidates:\n        count = 0\n        for s, e in accepted:\n            if adjacency:\n                overlaps = cand['start'] < e and s < cand['end']\n            else:\n                overlaps = cand['start'] <= e and s <= cand['end']\n            if overlaps:\n                count += 1\n        if count < capacity:\n            accepted.append((cand['start'], cand['end']))\n            if cand['cancelled']:\n                blocked.append((cand['id'], cand['index']))\n            else:\n                selected.append((cand['id'], cand['index']))\n        else:\n            rejected.append((cand['id'], cand['index']))\n    def sort_ids(pairs):\n        if cfg.get('report_order') == 'id':\n            try:\n                return [v for v, _ in sorted(pairs, key=lambda p: p[0])]\n            except Exception:\n                return [v for v, _ in sorted(pairs, key=lambda p: str(p[0]))]\n        return [v for v, _ in sorted(pairs, key=lambda p: p[1])]\n    return {'selected': sort_ids(selected), 'blocked': sort_ids(blocked), 'rejected': sort_ids(rejected)}\n", "policy.py": "POLICY = {\n    'adjacency_allowed': True,\n    'blackout_day': '2026-11-01',\n    'cancelled_blocks': True,\n    'capacity': 1,\n    'cutoff_hour': 17,\n    'cutoff_inclusive': True,\n    'duplicate_policy': 'first',\n    'duration_max': 120,\n    'lead_minutes': 30,\n    'priority_high_first': True,\n    'report_order': 'id',\n    'timezone': 'America/New_York',\n}\n", "helpers.py": "from datetime import datetime\n\ndef parse_aware(value):\n    if isinstance(value, datetime):\n        dt = value\n    elif isinstance(value, str):\n        text = value.strip()\n        if text.endswith('Z') or text.endswith('z'):\n            text = text[:-1] + '+00:00'\n        try:\n            dt = datetime.fromisoformat(text)\n        except Exception:\n            return None\n    else:\n        return None\n    if dt.tzinfo is None or dt.utcoffset() is None:\n        return None\n    return dt\n\ndef as_int(value):\n    if isinstance(value, bool):\n        return None\n    if isinstance(value, int):\n        return value\n    if isinstance(value, float) and value.is_integer():\n        return int(value)\n    return None\n"}}