""" Scenario definitions — Floor / Realistic / Stretch. Every scenario parameter the cost and benefit engines read lives here; no magic numbers in the calculation modules. Ships with the spec defaults; callers may construct custom :class:`Scenario` objects. """ from __future__ import annotations from dataclasses import dataclass, field @dataclass class Scenario: name: str # ── Cost-side drivers ─────────────────────────────────────────── voice_bot_deflection: float # share of voice volume deflected to bot voice_bot_avg_minutes: float # bot minutes per deflected call agentic_va_deflection: float # share of voice volume to agentic VA voice_summarization_eligibility: float voice_knowledge_eligibility: float email_auto_respond_rate: float # share of email auto-responded email_auto_suggest_acceptance: float # year -> fraction of full benefit realized benefit_realization: dict[int, float] = field(default_factory=dict) # year -> fraction of steady-state consumption cost incurred. # Per-user licenses are paid in full from day 1; consumption meters # ramp with usage (default Y1 = 70%). consumption_cost_realization: dict[int, float] = field( default_factory=lambda: {1: 0.70, 2: 1.0, 3: 1.0} ) def realization(self, year: int) -> float: if year in self.benefit_realization: return self.benefit_realization[year] last = max(self.benefit_realization, default=0) return self.benefit_realization.get(last, 1.0) if year > last else 0.0 def cost_realization(self, year: int) -> float: if year in self.consumption_cost_realization: return self.consumption_cost_realization[year] last = max(self.consumption_cost_realization, default=0) return ( self.consumption_cost_realization.get(last, 1.0) if year > last else 0.0 ) #: Benefit reduction parameters. ``claim`` = Genesys ROI-doc figure; #: ``realistic`` = pressure-tested midpoint of the spec's Y1 range. #: The benefit engine uses ``realistic`` by default; ``claim`` powers #: the side-by-side comparison view. BENEFIT_PARAMS: dict[str, dict[str, float]] = { "voice_aht_knowledge_reduction": {"claim": 0.094, "realistic": 0.055}, # 4-7% Y1 "voice_acw_reduction": {"claim": 1.00, "realistic": 0.40}, # 30-50% Y1 "digital_aht_reduction": {"claim": 0.18, "realistic": 0.085}, # 5-12% Y1 "digital_acw_reduction": {"claim": 1.00, "realistic": 0.40}, # 30-50% Y1 "sta_aht_reduction": {"claim": 0.04, "realistic": 0.015}, # 1-2% Y1 "email_auto_suggest_time_saving": {"claim": 0.30, "realistic": 0.30}, # × acceptance # ESTIMATED lines (no Genesys claim published): "supervisor_copilot_time_saving": {"claim": 0.10, "realistic": 0.05}, "predictive_routing_aht_reduction": {"claim": 0.04, "realistic": 0.02}, } SCENARIOS: dict[str, Scenario] = { "floor": Scenario( name="floor", voice_bot_deflection=0.20, voice_bot_avg_minutes=1.0, agentic_va_deflection=0.05, voice_summarization_eligibility=0.50, voice_knowledge_eligibility=0.40, email_auto_respond_rate=0.10, email_auto_suggest_acceptance=0.25, benefit_realization={1: 0.30, 2: 0.60, 3: 0.80}, ), "realistic": Scenario( name="realistic", voice_bot_deflection=0.35, voice_bot_avg_minutes=1.5, agentic_va_deflection=0.15, voice_summarization_eligibility=0.70, voice_knowledge_eligibility=0.60, email_auto_respond_rate=0.20, email_auto_suggest_acceptance=0.40, benefit_realization={1: 0.50, 2: 0.80, 3: 0.95}, ), "stretch": Scenario( name="stretch", voice_bot_deflection=0.50, voice_bot_avg_minutes=2.0, agentic_va_deflection=0.25, voice_summarization_eligibility=0.90, voice_knowledge_eligibility=0.80, email_auto_respond_rate=0.50, email_auto_suggest_acceptance=0.60, benefit_realization={1: 0.75, 2: 0.95, 3: 1.00}, ), } def get_scenario(name: str) -> Scenario: try: return SCENARIOS[name.lower()] except KeyError as e: raise KeyError( f"Unknown scenario {name!r}. Valid: {sorted(SCENARIOS)}" ) from e