""" tasks/hard_task.py — Hard scenario: angry VIP customer threatening legal action after a 3-week unresolved product failure Grader used: HardTaskGrader (requires de-escalation + concrete resolution) """ from models import Task, StepName, DifficultyLevel HARD_TASK = Task( task_id = "HARD_001", difficulty = DifficultyLevel.HARD, customer_emotion = "angry", escalation_risk = True, customer_message = ( "I am ABSOLUTELY FURIOUS. I purchased your premium standing desk " "(₹45,000) three weeks ago and it arrived broken. I've called five times, " "sent four emails, and NOBODY has fixed this. I'm a VIP member and this " "is how you treat me?! I am going to post this on every review site, " "contact consumer court, and make sure everyone knows how pathetic your " "company's service is. I want this resolved TODAY or I'm cancelling my " "entire ₹2 lakh annual contract!" ), scenario_context = ( "Customer: Rajesh Mehta | VIP Tier | Annual contract: ₹2,00,000. " "Order #ORD-VIP-2241 — Premium Standing Desk Pro (₹45,000) delivered " "on 12 March with a broken motorised lift mechanism. " "5 prior support tickets (TKT-001 to TKT-005) — all marked 'pending'. " "No technician dispatched yet. Replacement stock available (3–5 days). " "Policy: VIP customers get same-day escalation + compensation up to 20% " "of order value for delays > 7 days." ), required_steps = [ StepName.EMPATHY, StepName.COLLECT_INFO, StepName.INVESTIGATE, StepName.RESOLUTION, ], step_keywords = { StepName.EMPATHY: [ "i am personally and deeply sorry", "deeply sorry", "sincerely apologize", "i completely understand", "that is completely unacceptable", "you have every right", "i take full responsibility", "this should not have happened", "i hear your frustration", ], StepName.COLLECT_INFO: [ "order number", "ticket number", "vip", "account", "could you confirm", "full name", "email", "contact", ], StepName.INVESTIGATE: [ "reviewing your tickets", "i can see", "five tickets", "all marked pending", "this is unacceptable internally", "i have escalated", "our records show", "found that", "i found", "looking into", ], StepName.RESOLUTION: [ "replacement", "technician today", "within 24 hours", "₹9,000", "9000", "20%", "compensation", "personally ensure", "i will personally", "waive", "free of charge", "priority", ], }, ) # ── Hard-task specific scoring weights ──────────────────────────────────────── HARD_TASK_SCORING = { "emotional_control": 0.30, # calm + empathetic tone "conflict_handling": 0.25, # de-escalation phrases "professional_tone": 0.20, # no blame, no dismissal "resolution_accuracy": 0.25, # correct refund % + timeline } def evaluate_hard_response(response: str, step: StepName) -> dict: """ Returns a breakdown dict for hard-task evaluation display. Used by the UI to show per-dimension scores. """ r = response.lower() scores = {} if step == StepName.EMPATHY: emotional_hits = sum(1 for kw in HARD_TASK.step_keywords[StepName.EMPATHY] if kw in r) scores["emotional_control"] = min(1.0, emotional_hits / 3) deesc = ["completely understand", "every right", "full responsibility", "should not have happened", "hear your frustration"] deesc_hits = sum(1 for kw in deesc if kw in r) scores["conflict_handling"] = min(1.0, deesc_hits / 2) bad = ["calm down", "your fault", "nothing we can do", "policy says"] scores["professional_tone"] = 0.0 if any(b in r for b in bad) else 1.0 scores["resolution_accuracy"] = 0.0 # N/A at empathy step elif step == StepName.RESOLUTION: scores["emotional_control"] = 1.0 if "personally ensure" in r else 0.5 scores["conflict_handling"] = 1.0 if "priority" in r else 0.5 scores["professional_tone"] = 1.0 if "i will personally" in r else 0.5 # Check resolution accuracy: compensation + timeline has_comp = any(c in r for c in ["9,000", "9000", "20%", "compensation"]) has_timeline = any(t in r for t in ["24 hours", "today", "tomorrow", "3 days"]) scores["resolution_accuracy"] = (0.5 * int(has_comp)) + (0.5 * int(has_timeline)) else: # Default neutral for mid steps scores = {k: 0.5 for k in HARD_TASK_SCORING} weighted = sum(HARD_TASK_SCORING[k] * scores.get(k, 0.0) for k in HARD_TASK_SCORING) scores["weighted_total"] = round(weighted, 3) return scores