48 lines
1.4 KiB
Python
48 lines
1.4 KiB
Python
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from typing import Protocol
|
|
|
|
|
|
class QuoteStateLike(Protocol):
|
|
pending_image_urls: list
|
|
pending_requirements: list
|
|
quote_phase: str
|
|
quote_ready_turns: int
|
|
|
|
|
|
@dataclass
|
|
class QuoteStateMachine:
|
|
delay_turns: int = 1
|
|
|
|
def refresh(self, state: QuoteStateLike, phase_hint: str = "") -> None:
|
|
if phase_hint in {"idle", "collecting", "ready_to_quote", "waiting_result"}:
|
|
state.quote_phase = phase_hint
|
|
if phase_hint == "idle":
|
|
state.quote_ready_turns = 0
|
|
return
|
|
|
|
if not state.pending_image_urls:
|
|
state.quote_phase = "idle"
|
|
state.quote_ready_turns = 0
|
|
return
|
|
|
|
if state.quote_phase in {"ready_to_quote", "waiting_result"}:
|
|
return
|
|
|
|
state.quote_phase = "collecting"
|
|
|
|
def mark_ready(self, state: QuoteStateLike) -> None:
|
|
if state.quote_phase != "ready_to_quote":
|
|
state.quote_phase = "ready_to_quote"
|
|
state.quote_ready_turns = max(0, int(self.delay_turns))
|
|
|
|
def should_defer_batch_quote(self, state: QuoteStateLike, mark_ready: bool = False) -> bool:
|
|
if mark_ready and state.quote_phase != "ready_to_quote":
|
|
self.mark_ready(state)
|
|
|
|
if state.quote_phase == "ready_to_quote" and state.quote_ready_turns > 0:
|
|
state.quote_ready_turns -= 1
|
|
return True
|
|
return False
|