{"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 _is_int(value):\n    return isinstance(value, int) and not isinstance(value, bool)\n\ndef _field(record, names):\n    for name in names:\n        if name in record:\n            return record[name], True\n    return None, False\n\ndef _sorted_ids(pairs, report_order):\n    if report_order == 'id':\n        def key(pair):\n            value = pair[0]\n            if _is_int(value):\n                return (0, value, '')\n            return (1, 0, str(value))\n        ordered = sorted(pairs, key=key)\n    else:\n        ordered = sorted(pairs, key=lambda pair: pair[1])\n    return [pair[0] for pair in ordered]\n\ndef run(payload, policy):\n    policy = policy or {}\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    duplicate_policy = policy.get('duplicate_policy', 'first')\n    retained = {}\n    for index, record in enumerate(appointments):\n        if not isinstance(record, dict):\n            continue\n        appt_id, present = _field(record, ('id',))\n        if not present or appt_id is None or isinstance(appt_id, bool):\n            continue\n        try:\n            hash(appt_id)\n        except Exception:\n            continue\n        if appt_id not in retained:\n            retained[appt_id] = (index, record)\n        elif duplicate_policy == 'last':\n            retained[appt_id] = (index, record)\n    report_order = policy.get('report_order', 'input')\n    now_raw, _ = _field(payload, ('now',))\n    now = parse_aware_datetime(now_raw)\n    if now is None:\n        rejected = [(appt_id, idx) for appt_id, (idx, _rec) in retained.items()]\n        return {'selected': [], 'blocked': [], 'rejected': _sorted_ids(rejected, report_order)}\n    now_utc = now.astimezone(timezone.utc)\n    try:\n        tz = ZoneInfo(str(policy.get('timezone', 'UTC')))\n    except Exception:\n        rejected = [(appt_id, idx) for appt_id, (idx, _rec) in retained.items()]\n        return {'selected': [], 'blocked': [], 'rejected': _sorted_ids(rejected, report_order)}\n    lead_minutes = policy.get('lead_minutes', 0)\n    duration_max = policy.get('duration_max')\n    cutoff_hour = policy.get('cutoff_hour')\n    cutoff_inclusive = policy.get('cutoff_inclusive', True)\n    blackout_day = policy.get('blackout_day')\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    if not _is_int(lead_minutes) or not _is_int(duration_max) or not _is_int(cutoff_hour) or not _is_int(capacity):\n        rejected = [(appt_id, idx) for appt_id, (idx, _rec) in retained.items()]\n        return {'selected': [], 'blocked': [], 'rejected': _sorted_ids(rejected, report_order)}\n    earliest = now_utc + timedelta(minutes=lead_minutes)\n    candidates = []\n    rejected = []\n    for appt_id, (index, record) in retained.items():\n        start_raw, _ = _field(record, ('start', 'start_time'))\n        duration_raw, _ = _field(record, ('duration_minutes', 'duration', 'duration_min', 'minutes'))\n        priority_raw, _ = _field(record, ('priority',))\n        cancelled_raw, cancelled_present = _field(record, ('cancelled', 'canceled'))\n        if not cancelled_present:\n            cancelled_raw = False\n        start = parse_aware_datetime(start_raw)\n        valid = True\n        if start is None:\n            valid = False\n        if not _is_int(duration_raw) or duration_raw <= 0 or duration_raw > duration_max:\n            valid = False\n        if not _is_int(priority_raw):\n            valid = False\n        if not isinstance(cancelled_raw, bool):\n            valid = False\n        if not valid:\n            rejected.append((appt_id, index))\n            continue\n        start_utc = start.astimezone(timezone.utc)\n        end_utc = start_utc + timedelta(minutes=duration_raw)\n        if start_utc < earliest:\n            rejected.append((appt_id, index))\n            continue\n        local_start = start_utc.astimezone(tz)\n        if blackout_day is not None and local_start.date().isoformat() == str(blackout_day):\n            rejected.append((appt_id, index))\n            continue\n        try:\n            cutoff = datetime(local_start.year, local_start.month, local_start.day, cutoff_hour, 0, tzinfo=tz)\n        except Exception:\n            rejected.append((appt_id, index))\n            continue\n        if cutoff_inclusive:\n            if end_utc > cutoff:\n                rejected.append((appt_id, index))\n                continue\n        else:\n            if end_utc >= cutoff:\n                rejected.append((appt_id, index))\n                continue\n        if cancelled_raw and not cancelled_blocks:\n            rejected.append((appt_id, index))\n            continue\n        candidates.append({'id': appt_id, 'index': index, 'priority': priority_raw, 'start': start_utc, 'end': end_utc, 'cancelled': cancelled_raw})\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    selected = []\n    blocked = []\n    accepted_intervals = []\n    for item in candidates:\n        overlap_count = 0\n        for other_start, other_end in accepted_intervals:\n            if intervals_overlap(item['start'], item['end'], other_start, other_end, adjacency_allowed):\n                overlap_count += 1\n        if overlap_count < capacity:\n            accepted_intervals.append((item['start'], item['end']))\n            if item['cancelled'] and cancelled_blocks:\n                blocked.append((item['id'], item['index']))\n            else:\n                selected.append((item['id'], item['index']))\n        else:\n            rejected.append((item['id'], item['index']))\n    return {'selected': _sorted_ids(selected, report_order), 'blocked': _sorted_ids(blocked, report_order), 'rejected': _sorted_ids(rejected, report_order)}\n", "policy.py": "POLICY = {\n    'cutoff_hour': 18,\n    'cutoff_inclusive': False,\n    'lead_minutes': 60,\n    'timezone': 'UTC',\n    'adjacency_allowed': False,\n    'cancelled_blocks': False,\n    'duplicate_policy': 'last',\n    'duration_max': 90,\n    'capacity': 2,\n    'report_order': 'input',\n    'blackout_day': '2026-11-02',\n    'priority_high_first': False,\n}\n", "helpers.py": "from datetime import datetime, timezone\n\ndef parse_aware_datetime(value):\n    if isinstance(value, datetime):\n        parsed = 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            parsed = datetime.fromisoformat(text)\n        except Exception:\n            return None\n    else:\n        return None\n    if parsed.tzinfo is None or parsed.utcoffset() is None:\n        return None\n    return parsed.astimezone(timezone.utc)\n\ndef intervals_overlap(start, end, other_start, other_end, adjacency_allowed):\n    if adjacency_allowed:\n        return start < other_end and other_start < end\n    return start <= other_end and other_start <= end\n"}}