File size: 5,821 Bytes
ca95ab5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
"""

Explanation Generation

Generates natural language explanations for errors found

Provides educational context and learning suggestions

"""

from typing import Dict, Any


def generate_explanation(error: Dict[str, Any]) -> str:
    """

    Generate human-readable explanation for an error.

    

    Args:

        error: Error dictionary with type, found, correct, step_number, etc.

        

    Returns:

        Natural language explanation string (2-3 sentences)

    """
    error_type = error.get("type", "unknown")
    found = error.get("found", "")
    correct = error.get("correct", "")
    operation = error.get("operation", "")
    step_number = error.get("step_number", 0)
    
    # Extract numbers from found and correct
    import re
    found_nums = re.findall(r'\d+\.?\d*', found)
    correct_nums = re.findall(r'\d+\.?\d*', correct)
    
    # Generate explanation based on error type
    if error_type == "calculation_error":
        explanation = _explain_arithmetic_error(found, correct, operation, found_nums, correct_nums)
    elif error_type == "logical_error":
        explanation = _explain_logical_error(error, step_number)
    elif error_type == "operation_mismatch":
        explanation = _explain_operation_mismatch(error, found, correct)
    elif error_type == "semantic_error":
        explanation = _explain_semantic_error(error, found, correct)
    else:
        explanation = _explain_generic_error(found, correct)
    
    # Add learning context
    learning_tip = _get_learning_tip(error_type, operation)
    if learning_tip:
        explanation += f" {learning_tip}"
    
    return explanation


def _explain_arithmetic_error(found: str, correct: str, operation: str, found_nums: list, correct_nums: list) -> str:
    """Explain arithmetic calculation errors."""
    if not found_nums or not correct_nums:
        return f"You wrote '{found}', but the correct answer is '{correct}'."
    
    try:
        found_result = float(found_nums[-1]) if found_nums else 0
        correct_result = float(correct_nums[-1]) if correct_nums else 0
        
        if len(found_nums) >= 2:
            operand1 = float(found_nums[0])
            operand2 = float(found_nums[1])
            
            op_names = {
                '+': 'add',
                '-': 'subtract',
                '*': 'multiply',
                '/': 'divide'
            }
            op_name = op_names.get(operation, 'calculate')
            
            explanation = f"You wrote {found_result}, but {operand1} {operation} {operand2} actually equals {correct_result}. "
            
            if operation == '+':
                explanation += f"When you add {operand2} to {operand1}, you get {correct_result}, not {found_result}."
            elif operation == '-':
                explanation += f"When you subtract {operand2} from {operand1}, you count down: {operand1}, {correct_result}. So {operand1} - {operand2} = {correct_result}, not {found_result}."
            elif operation == '*':
                explanation += f"When you multiply {operand1} by {operand2}, you get {correct_result}, not {found_result}."
            elif operation == '/':
                explanation += f"When you divide {operand1} by {operand2}, you get {correct_result}, not {found_result}."
            else:
                explanation += f"The correct calculation gives {correct_result}, not {found_result}."
            
            return explanation
    except:
        pass
    
    return f"You wrote '{found}', but the correct answer is '{correct}'."


def _explain_logical_error(error: Dict[str, Any], step_number: int) -> str:
    """Explain logical consistency errors."""
    description = error.get("description", "There is a logical inconsistency in your reasoning.")
    
    explanation = f"In step {step_number}, {description.lower()} "
    explanation += "This contradicts your earlier statements or creates circular reasoning."
    
    return explanation


def _explain_operation_mismatch(error: Dict[str, Any], found: str, correct: str) -> str:
    """Explain operation mismatch errors."""
    description = error.get("description", "The operation doesn't match what you described.")
    
    explanation = f"{description} "
    explanation += "Make sure the mathematical operation matches what you're trying to do in the problem."
    
    return explanation


def _explain_semantic_error(error: Dict[str, Any], found: str, correct: str) -> str:
    """Explain semantic inconsistency errors."""
    description = error.get("description", "The meaning doesn't match the mathematical expression.")
    
    explanation = f"{description} "
    explanation += "Review the step to ensure it follows logically from the previous steps."
    
    return explanation


def _explain_generic_error(found: str, correct: str) -> str:
    """Generic error explanation."""
    return f"You wrote '{found}', but the correct answer should be '{correct}'. Please review your calculation."


def _get_learning_tip(error_type: str, operation: str) -> str:
    """Get learning tip based on error type."""
    tips = {
        "calculation_error": "Try double-checking your arithmetic by working through the problem step by step.",
        "logical_error": "Make sure each step follows logically from the previous one and doesn't contradict earlier statements.",
        "operation_mismatch": "Before writing the math, think about which operation matches what you're trying to do.",
        "semantic_error": "Review how this step connects to the overall problem and previous steps."
    }
    
    return tips.get(error_type, "Practice similar problems to improve your understanding.")