| """Spawn budget and regular attempt probabilities (R3).""" | |
| from __future__ import annotations | |
| from typing import Dict, Mapping | |
| DEFAULT_BUDGET = { | |
| "PREP": 0.0, | |
| "MORNING": 2.5, | |
| "AFTERNOON": 3.5, | |
| "DUSK": 2.5, | |
| "CLOSING": 0.5, | |
| "NIGHT": 0.0, | |
| } | |
| DEFAULT_P_REGULAR = { | |
| "MORNING": 0.15, | |
| "AFTERNOON": 0.30, | |
| "DUSK": 0.50, | |
| "CLOSING": 0.10, | |
| } | |
| def spawn_budget(phase: str, table: Mapping[str, float] | None = None) -> float: | |
| t = table or DEFAULT_BUDGET | |
| return float(t.get(phase, 0.0) or 0.0) | |
| def p_regular_attempt(phase: str, table: Mapping[str, float] | None = None) -> float: | |
| t = table or DEFAULT_P_REGULAR | |
| return float(t.get(phase, 0.0) or 0.0) | |
| def arrival_interval(phase_limit: float, budget: float, jitter: float, rng) -> float: | |
| """Mean spacing with ±jitter factor already applied externally.""" | |
| if budget <= 0 or phase_limit <= 0: | |
| return phase_limit | |
| base = phase_limit / max(budget, 0.01) | |
| return base * float(jitter) | |
| # reseal-product R53 | |