Spaces:
Running
Running
| from __future__ import annotations | |
| import re | |
| from typing import List, Optional | |
| from models import ParsedContext | |
| def extract_section(text: str, start_label: str, end_labels: List[str]) -> str: | |
| start_idx = text.find(start_label) | |
| if start_idx == -1: | |
| return "" | |
| start_idx += len(start_label) | |
| remaining = text[start_idx:] | |
| end_positions = [] | |
| for label in end_labels: | |
| idx = remaining.find(label) | |
| if idx != -1: | |
| end_positions.append(idx) | |
| if end_positions: | |
| end_idx = min(end_positions) | |
| return remaining[:end_idx].strip() | |
| return remaining.strip() | |
| def parse_hidden_context(message: str) -> ParsedContext: | |
| raw = message or "" | |
| visible_user_text = "" | |
| question_text = "" | |
| options_text = "" | |
| recent_conversation = "" | |
| if "USER_MESSAGE:" in raw: | |
| visible_user_text = extract_section(raw, "USER_MESSAGE:", []) | |
| elif "Latest player message:" in raw: | |
| visible_user_text = extract_section(raw, "Latest player message:", []) | |
| elif "Player message:" in raw: | |
| visible_user_text = extract_section(raw, "Player message:", []) | |
| else: | |
| visible_user_text = raw.strip() | |
| if "Question:" in raw: | |
| question_text = extract_section( | |
| raw, | |
| "Question:", | |
| [ | |
| "\nOptions:", | |
| "\nPlayer balance:", | |
| "\nLast outcome:", | |
| "\nRecent conversation:", | |
| "\nLatest player message:", | |
| "\nPlayer message:", | |
| "\nUSER_MESSAGE:", | |
| ], | |
| ) | |
| if "Options:" in raw: | |
| options_text = extract_section( | |
| raw, | |
| "Options:", | |
| [ | |
| "\nPlayer balance:", | |
| "\nLast outcome:", | |
| "\nRecent conversation:", | |
| "\nLatest player message:", | |
| "\nPlayer message:", | |
| "\nUSER_MESSAGE:", | |
| ], | |
| ) | |
| if "Recent conversation:" in raw: | |
| recent_conversation = extract_section( | |
| raw, | |
| "Recent conversation:", | |
| [ | |
| "\nLatest player message:", | |
| "\nPlayer message:", | |
| "\nUSER_MESSAGE:", | |
| ], | |
| ) | |
| combined_parts = [] | |
| if question_text: | |
| combined_parts.append(question_text.strip()) | |
| if options_text: | |
| combined_parts.append(options_text.strip()) | |
| combined_question_block = "\n".join([p for p in combined_parts if p]).strip() | |
| if not combined_question_block: | |
| combined_question_block = raw.strip() | |
| return ParsedContext( | |
| raw_message=raw, | |
| visible_user_text=visible_user_text.strip(), | |
| full_context_text=raw.strip(), | |
| question_text=question_text.strip(), | |
| options_text=options_text.strip(), | |
| combined_question_block=combined_question_block.strip(), | |
| recent_conversation=recent_conversation.strip(), | |
| ) | |
| def detect_help_mode(user_text: str, supplied: Optional[str]) -> str: | |
| lower = (user_text or "").lower().strip() | |
| if supplied in {"hint", "walkthrough", "answer"}: | |
| if "hint" in lower: | |
| return "hint" | |
| if ( | |
| "walkthrough" in lower | |
| or "step by step" in lower | |
| or "work through" in lower | |
| or "explain step by step" in lower | |
| ): | |
| return "walkthrough" | |
| if "why" in lower or "explain" in lower: | |
| return "walkthrough" | |
| return supplied | |
| if lower in {"hint", "just a hint", "hint please", "small hint"}: | |
| return "hint" | |
| if "hint" in lower: | |
| return "hint" | |
| if ( | |
| "walkthrough" in lower | |
| or "step by step" in lower | |
| or "work through" in lower | |
| or "explain step by step" in lower | |
| ): | |
| return "walkthrough" | |
| if "why" in lower or "explain" in lower: | |
| return "walkthrough" | |
| return "answer" | |
| def user_is_referring_to_existing_question(user_text: str, question_text: str) -> bool: | |
| lower = (user_text or "").lower().strip() | |
| if not question_text: | |
| return False | |
| short_refs = { | |
| "help", | |
| "hint", | |
| "why", | |
| "why?", | |
| "explain", | |
| "explain it", | |
| "explain this", | |
| "answer", | |
| "what's the answer", | |
| "what is the answer", | |
| "is it a", | |
| "is it b", | |
| "is it c", | |
| "is it d", | |
| "is it e", | |
| "which one", | |
| "which option", | |
| "what do i do first", | |
| "what do i do", | |
| "how do i start", | |
| "are you sure", | |
| "can you help", | |
| "help me", | |
| "i don't get it", | |
| "i dont get it", | |
| "why is it c", | |
| "why is it b", | |
| "why is it a", | |
| "why is it d", | |
| "why is it e", | |
| "what is the question asking me to do", | |
| "what is this asking", | |
| "what do you need", | |
| } | |
| if lower in short_refs: | |
| return True | |
| if any( | |
| phrase in lower | |
| for phrase in [ | |
| "is it ", | |
| "why", | |
| "hint", | |
| "explain", | |
| "answer", | |
| "help", | |
| "first step", | |
| "what is the question asking", | |
| "what is this asking", | |
| "what do you need", | |
| ] | |
| ): | |
| return True | |
| return False | |
| def mentions_choice_letter(user_text: str) -> Optional[str]: | |
| lower = (user_text or "").lower().strip() | |
| m = re.search(r"\b(?:is it|answer is|it's|its|option|choice)\s*([a-e])\b", lower) | |
| if m: | |
| return m.group(1).upper() | |
| m = re.search(r"\bwhy is it\s*([a-e])\b", lower) | |
| if m: | |
| return m.group(1).upper() | |
| if lower in {"a", "b", "c", "d", "e"}: | |
| return lower.upper() | |
| return None |