Source code for sim_panel.policies.manual
from __future__ import annotations
from typing import List, Sequence
import numpy as np
from sim_panel.policies.base import Policy
from sim_panel.policies.types import ExposureDecision
[docs]
class ManualAssignmentPolicy(Policy):
"""
Manual exposure from a user-provided mapping function.
Loader/wiring from file happens elsewhere; policy stays pure.
The function takes (panelist_id, t, product_ids) and returns:
- product_id (str), or
- list[str]
"""
[docs]
def decide(
self,
*,
rng: np.random.Generator, # unused; kept for API parity
panelist_id: str,
t: int,
product_ids: Sequence[str],
) -> ExposureDecision:
if self.cfg.manual_assignment_fn is None:
raise ValueError("ManualAssignmentPolicy requires cfg.manual_assignment_fn")
out = self.cfg.manual_assignment_fn(panelist_id, t, product_ids)
chosen: List[str] = [out] if isinstance(out, str) else list(out)
return ExposureDecision(
panelist_id=panelist_id,
t=t,
policy=self.cfg.name,
evaluate_product_ids=chosen,
selection=None,
meta={"method": "manual_fn"},
)