Source code for sim_panel.policies.types

from __future__ import annotations

from dataclasses import dataclass
from typing import Any, Dict, List, Literal, Optional, Protocol, Sequence


PolicyName = Literal["random", "manual", "self_selection"]
RandomMode = Literal["balanced_quota", "iid_probs"]


[docs] @dataclass(frozen=True) class SelectionSpec: """ Self-selection exposure spec. Policy controls what is SHOWN (choice_set). Panelist returns what they WANT (requested_product_ids) later. Generator may apply operational rules (budget caps, filtering) later. """ choice_set: List[str] allow_empty: bool = True
[docs] @dataclass(frozen=True) class ExposureDecision: """ Policy decision for one ``(panelist_id, t)``. Exactly one of the following fields should be populated: - ``evaluate_product_ids`` for random/manual exposure. - ``selection`` for self-selection exposure. """ panelist_id: str t: int policy: PolicyName evaluate_product_ids: Optional[List[str]] = None selection: Optional[SelectionSpec] = None meta: Optional[Dict[str, Any]] = None
[docs] class ManualAssignmentFn(Protocol): """ Manual assignment hook. Expected to be deterministic conditional on inputs. Returns either a single product_id or a list of product_ids to evaluate. """ def __call__(self, panelist_id: str, t: int, product_ids: Sequence[str]) -> str | List[str]: ...