import re from .explainer_types import ExplainerResult, ExplainerScaffold def explain_probability_question(text: str): low = (text or "").lower() probability_signals = [ "probability", "chance", "odds", "random", "chosen at random", "selected at random", "picked at random", "drawn", "without replacement", "with replacement", ] if not any(signal in low for signal in probability_signals): return None subtype = "dependent_events" if "without replacement" in low else "independent_events" if "with replacement" in low else "general_probability" result = ExplainerResult( understood=True, topic="probability", summary="This is a probability problem. The goal is to compare favorable outcomes to total possible outcomes.", asks_for="the probability of a specific event or combination of events", plain_english="Probability questions become much easier once you define exactly what counts as success and what the full sample space is.", ) scaffold = ExplainerScaffold( concept="Probability compares favorable outcomes to total outcomes.", ask="Identify what counts as a successful outcome and what the total possible outcomes are.", target="Set up favorable ÷ total before calculating.", answer_hidden=True, solution_path_type=subtype, ) numbers = re.findall(r"\b\d+\b", low) if numbers: result.givens.append(f"Numbers mentioned: {', '.join(numbers[:5])}") else: result.givens.append("A situation involving possible outcomes is described.") result.relationships = [ "Probability = favorable outcomes ÷ total possible outcomes", ] result.needed_concepts = [ "favorable vs total outcomes", "independent vs dependent events", "complement rule", ] result.trap_notes = [ "Make sure you correctly identify the total number of possible outcomes.", "Check whether events are independent or dependent.", "Watch for 'at least' — often easier to use the complement.", "Be careful not to double count outcomes.", ] result.strategy_hint = "Start by identifying all possible outcomes, then count how many satisfy the condition." if "without replacement" in low: result.constraints.append("The total number of items decreases after each draw.") result.relationships.append("The probabilities change after each selection.") if "with replacement" in low: result.relationships.append("The probabilities stay the same for each selection.") if "at least" in low: result.relationships.append("This may be easier through the complement: 1 − probability of the opposite event.") if "both" in low or "and" in low: result.relationships.append("You may need to combine probabilities of multiple events occurring together.") if "or" in low: result.relationships.append("You may need to consider multiple favorable cases without double counting.") scaffold.setup_actions = [ "Define what counts as a favorable outcome.", "Count or describe the total possible outcomes.", "Check whether the events are independent or dependent.", ] scaffold.intermediate_steps = [ "If multiple events occur together, decide whether to multiply or add probabilities.", "If the wording says 'at least', consider using the complement.", "Check whether order matters.", ] scaffold.first_move = "Start by identifying the total number of outcomes." scaffold.next_hint = "Then count how many outcomes match the condition." scaffold.common_traps = [ "Forgetting the total outcomes.", "Mixing up 'and' vs 'or'.", "Ignoring replacement vs no replacement.", ] scaffold.key_operations = [ "count the sample space", "count favorable cases", "choose multiply/add/complement appropriately", ] scaffold.hint_ladder = [ "What counts as success here?", "What is the full sample space?", "Do you need multiplication, addition, or the complement rule?", ] result.teaching_points = [ "Probability = favorable / total.", "Use multiplication for linked 'and' events when appropriate.", "Use the complement when 'at least' is easier to solve indirectly.", ] result.scaffold = scaffold result.meta = { "intent": "explain_question", "bridge_ready": True, "hint_style": "step_ready", "subtype": subtype, } return result