import hashlib import random from typing import Any from app.config import settings SCENE_CATALOG = [ ("home_bedroom", "居家-卧室", "Let's talk about your morning routine."), ("home_kitchen", "居家-厨房", "What would you like to cook today?"), ("home_study", "居家-书房", "Shall we review your vocabulary?"), ("school", "校内", "How was your class today?"), ("commute", "通勤", "What do you see on your way?"), ("exercise", "运动", "How do you stay active?"), ("dining", "用餐", "What are you having for dinner?"), ] GENERIC_GREETING = "Hello! How can I help you practice English today?" class SceneEngine: def __init__(self, threshold: float | None = None) -> None: self.threshold = threshold or settings.scene_confidence_threshold def _derive_seed(self, device_id: str, timestamp: int, hints: dict[str, Any]) -> int: raw = f"{device_id}:{timestamp}:{hints.get('mode', '')}" return int(hashlib.md5(raw.encode()).hexdigest()[:8], 16) def analyze( self, device_id: str, timestamp: int, context_hints: dict[str, Any] | None = None, ) -> dict[str, Any]: hints = context_hints or {} rng = random.Random(self._derive_seed(device_id, timestamp, hints)) if hints.get("scene"): scene_key = hints["scene"] match = next((s for s in SCENE_CATALOG if s[0] == scene_key), None) if match: confidence = float(hints.get("confidence", 0.85)) return self._build_result(match, confidence) idx = rng.randint(0, len(SCENE_CATALOG) - 1) confidence = round(rng.uniform(0.55, 0.95), 2) return self._build_result(SCENE_CATALOG[idx], confidence) def _build_result(self, scene: tuple[str, str, str], confidence: float) -> dict[str, Any]: scene_key, scene_label, prompt = scene use_generic = confidence < self.threshold return { "scene": scene_label, "scene_key": scene_key, "confidence": confidence, "greeting_strategy": "generic" if use_generic else "contextual", "suggested_intent": GENERIC_GREETING if use_generic else prompt, }