✨ Add latex generating in steps
This commit is contained in:
		| @@ -56,13 +56,12 @@ class SolverService { | |||||||
|     final steps = <CalculationStep>[]; |     final steps = <CalculationStep>[]; | ||||||
|     steps.add( |     steps.add( | ||||||
|       CalculationStep( |       CalculationStep( | ||||||
|         title: "第一步:表达式求值", |         title: '第一步:表达式求值', | ||||||
|         explanation: "这是一个标准的数学表达式,我们将直接计算其结果。", |         explanation: '这是一个标准的数学表达式,我们将直接计算其结果。', | ||||||
|         formula: input, |         formula: input, | ||||||
|       ), |       ), | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|     // **FIXED**: Correct usage of the math_expressions library |  | ||||||
|     Parser p = Parser(); |     Parser p = Parser(); | ||||||
|     Expression exp = p.parse(input); |     Expression exp = p.parse(input); | ||||||
|     ContextModel cm = ContextModel(); |     ContextModel cm = ContextModel(); | ||||||
| @@ -75,134 +74,118 @@ class SolverService { | |||||||
|   CalculationResult _solveLinearEquation(String input) { |   CalculationResult _solveLinearEquation(String input) { | ||||||
|     final steps = <CalculationStep>[]; |     final steps = <CalculationStep>[]; | ||||||
|     steps.add( |     steps.add( | ||||||
|       CalculationStep(title: "原方程", explanation: "这是一元一次方程。", formula: input), |       CalculationStep( | ||||||
|  |         title: '原方程', | ||||||
|  |         explanation: '这是一元一次方程。', | ||||||
|  |         formula: '\$\$$input\$\$', | ||||||
|  |       ), | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|     // 解析方程: ax+b=cx+d |  | ||||||
|     final parts = _parseLinearEquation(input); |     final parts = _parseLinearEquation(input); | ||||||
|     final a = parts.a, b = parts.b, c = parts.c, d = parts.d; |     final a = parts.a, b = parts.b, c = parts.c, d = parts.d; | ||||||
|  |  | ||||||
|     // 移项合并 |  | ||||||
|     final newA = a - c; |     final newA = a - c; | ||||||
|     final newD = d - b; |     final newD = d - b; | ||||||
|  |  | ||||||
|     steps.add( |     steps.add( | ||||||
|       CalculationStep( |       CalculationStep( | ||||||
|         title: "第一步:移项", |         title: '第一步:移项', | ||||||
|         explanation: "将所有含 x 的项移到等式左边,常数项移到右边。", |         explanation: '将所有含 x 的项移到等式左边,常数项移到右边。', | ||||||
|         formula: |         formula: | ||||||
|             "${a}x ${c >= 0 ? '-' : '+'} ${c.abs()}x = $d ${b >= 0 ? '-' : '+'} ${b.abs()}", |             '\$\$${a}x ${c >= 0 ? '-' : '+'} ${c.abs()}x = $d ${b >= 0 ? '-' : '+'} ${b.abs()}\$\$', | ||||||
|       ), |       ), | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|     steps.add( |     steps.add( | ||||||
|       CalculationStep( |       CalculationStep( | ||||||
|         title: "第二步:合并同类项", |         title: '第二步:合并同类项', | ||||||
|         explanation: "合并等式两边的项。", |         explanation: '合并等式两边的项。', | ||||||
|         formula: "${newA}x = $newD", |         formula: '\$\$${newA}x = $newD\$\$', | ||||||
|       ), |       ), | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|     // 求解x |  | ||||||
|     if (newA == 0) { |     if (newA == 0) { | ||||||
|       if (newD == 0) { |       return CalculationResult( | ||||||
|         return CalculationResult(steps: steps, finalAnswer: "有无穷多解"); |         steps: steps, | ||||||
|       } else { |         finalAnswer: newD == 0 ? '有无穷多解' : '无解', | ||||||
|         return CalculationResult(steps: steps, finalAnswer: "无解"); |       ); | ||||||
|       } |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     final x = newD / newA; |     final x = newD / newA; | ||||||
|     steps.add( |     steps.add( | ||||||
|       CalculationStep( |       CalculationStep( | ||||||
|         title: "第三步:求解 x", |         title: '第三步:求解 x', | ||||||
|         explanation: "两边同时除以 x 的系数 ($newA)。", |         explanation: '两边同时除以 x 的系数 ($newA)。', | ||||||
|         formula: "x = $newD / $newA", |         formula: '\$\$x = \frac{$newD}{$newA}\$\$', | ||||||
|       ), |       ), | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|     return CalculationResult(steps: steps, finalAnswer: "x = $x"); |     return CalculationResult(steps: steps, finalAnswer: '\$\$x = $x\$\$'); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /// 3. 求解一元二次方程 (升级版) |   /// 3. 求解一元二次方程 (升级版) | ||||||
|   CalculationResult _solveQuadraticEquation(String input) { |   CalculationResult _solveQuadraticEquation(String input) { | ||||||
|     final steps = <CalculationStep>[]; |     final steps = <CalculationStep>[]; | ||||||
|  |  | ||||||
|     // 整理成 ax^2+bx+c=0 的形式并提取系数 |  | ||||||
|     final eqParts = input.split('='); |     final eqParts = input.split('='); | ||||||
|     if (eqParts.length != 2) throw Exception("方程格式错误,应包含一个 '='。"); |     if (eqParts.length != 2) throw Exception("方程格式错误,应包含一个 '='。"); | ||||||
|  |  | ||||||
|     final leftCoeffs = _parsePolynomial(eqParts[0]); |     final leftCoeffs = _parsePolynomial(eqParts[0]); | ||||||
|     final rightCoeffs = _parsePolynomial(eqParts[1]); |     final rightCoeffs = _parsePolynomial(eqParts[1]); | ||||||
|  |  | ||||||
|     // 移项合并 |  | ||||||
|     final a = (leftCoeffs[2] ?? 0) - (rightCoeffs[2] ?? 0); |     final a = (leftCoeffs[2] ?? 0) - (rightCoeffs[2] ?? 0); | ||||||
|     final b = (leftCoeffs[1] ?? 0) - (rightCoeffs[1] ?? 0); |     final b = (leftCoeffs[1] ?? 0) - (rightCoeffs[1] ?? 0); | ||||||
|     final c = (leftCoeffs[0] ?? 0) - (rightCoeffs[0] ?? 0); |     final c = (leftCoeffs[0] ?? 0) - (rightCoeffs[0] ?? 0); | ||||||
|  |  | ||||||
|     if (a == 0) { |     if (a == 0) { | ||||||
|       // 如果 a=0, 这实际上是一个一元一次方程 |       return _solveLinearEquation('${b}x+$c=0'); | ||||||
|       return _solveLinearEquation("${b}x+${c}=0"); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // **FIXED**: Corrected typo 'ax' to 'a' |  | ||||||
|     steps.add( |     steps.add( | ||||||
|       CalculationStep( |       CalculationStep( | ||||||
|         title: "第一步:整理方程", |         title: '第一步:整理方程', | ||||||
|         explanation: "将方程整理成标准形式 ax^2+bx+c=0。", |         explanation: r'将方程整理成标准形式 $ax^2+bx+c=0$。', | ||||||
|         formula: |         formula: | ||||||
|             "${a}x^2 ${b >= 0 ? '+' : ''} ${b}x ${c >= 0 ? '+' : ''} $c = 0", |             '\$\$${a}x^2 ${b >= 0 ? '+' : ''} ${b}x ${c >= 0 ? '+' : ''} $c = 0\$\$', | ||||||
|       ), |       ), | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|     // 尝试因式分解 (十字相乘法) |  | ||||||
|     if (a == a.round() && b == b.round() && c == c.round()) { |     if (a == a.round() && b == b.round() && c == c.round()) { | ||||||
|       final factors = _tryFactorization(a.toInt(), b.toInt(), c.toInt()); |       final factors = _tryFactorization(a.toInt(), b.toInt(), c.toInt()); | ||||||
|       if (factors != null) { |       if (factors != null) { | ||||||
|         steps.add( |         steps.add( | ||||||
|           CalculationStep( |           CalculationStep( | ||||||
|             title: "第二步:因式分解法 (十字相乘)", |             title: '第二步:因式分解法 (十字相乘)', | ||||||
|             explanation: "我们发现可以将方程分解为两个一次因式的乘积。", |             explanation: '我们发现可以将方程分解为两个一次因式的乘积。', | ||||||
|             formula: factors.formula, |             formula: factors.formula, | ||||||
|           ), |           ), | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|         steps.add( |         steps.add( | ||||||
|           CalculationStep( |           CalculationStep( | ||||||
|             title: "第三步:求解", |             title: '第三步:求解', | ||||||
|             explanation: "分别令每个因式等于 0,解出 x。", |             explanation: '分别令每个因式等于 0,解出 x。', | ||||||
|             formula: "解得 ${factors.solution}", |             formula: '解得 ${factors.solution}', | ||||||
|           ), |           ), | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|         return CalculationResult(steps: steps, finalAnswer: factors.solution); |         return CalculationResult(steps: steps, finalAnswer: factors.solution); | ||||||
|       } else { |  | ||||||
|         steps.add( |  | ||||||
|           CalculationStep( |  | ||||||
|             title: "第二步:选择解法", |  | ||||||
|             explanation: "尝试因式分解失败,我们选择使用求根公式法。", |  | ||||||
|             formula: "\$\\Delta = b^2 - 4ac\$", |  | ||||||
|           ), |  | ||||||
|         ); |  | ||||||
|       } |       } | ||||||
|     } else { |  | ||||||
|       steps.add( |  | ||||||
|         CalculationStep( |  | ||||||
|           title: "第二步:选择解法", |  | ||||||
|           explanation: "系数包含小数,我们使用求根公式法。", |  | ||||||
|           formula: "\$\\Delta = b^2 - 4ac\$", |  | ||||||
|         ), |  | ||||||
|       ); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // 使用求根公式法 |     steps.add( | ||||||
|  |       CalculationStep( | ||||||
|  |         title: '第二步:选择解法', | ||||||
|  |         explanation: '无法进行因式分解,我们选择使用求根公式法。', | ||||||
|  |         formula: r'\$\$\Delta = b^2 - 4ac\$\$', | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |  | ||||||
|     final delta = b * b - 4 * a * c; |     final delta = b * b - 4 * a * c; | ||||||
|     steps.add( |     steps.add( | ||||||
|       CalculationStep( |       CalculationStep( | ||||||
|         title: "第三步:计算判别式 (Delta)", |         title: '第三步:计算判别式 (Delta)', | ||||||
|         explanation: "\$\\Delta = ($b)^2 - 4 \\cdot ($a) \\cdot ($c) = $delta", |         explanation: | ||||||
|         // **FIXED**: Removed unnecessary braces for linter warning |             '\$\$\Delta = b^2 - 4ac = ($b)^2 - 4 \cdot ($a) \cdot ($c) = $delta\$\$', | ||||||
|         formula: "\$\\Delta = $delta", |         formula: '\$\$\Delta = $delta\$\$', | ||||||
|       ), |       ), | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
| @@ -211,40 +194,40 @@ class SolverService { | |||||||
|       final x2 = (-b - sqrt(delta)) / (2 * a); |       final x2 = (-b - sqrt(delta)) / (2 * a); | ||||||
|       steps.add( |       steps.add( | ||||||
|         CalculationStep( |         CalculationStep( | ||||||
|           title: "第四步:应用求根公式", |           title: '第四步:应用求根公式', | ||||||
|           explanation: |           explanation: | ||||||
|               "因为 \$\\Delta > 0\$,方程有两个不相等的实数根。公式: \$x = \\frac{-b \\pm \\sqrt{\\Delta}}{2a}\$", |               r'因为 $\Delta > 0$,方程有两个不相等的实数根。公式: $x = \frac{-b \pm \sqrt{\Delta}}{2a}$。', | ||||||
|           formula: |           formula: | ||||||
|               "x₁ = ${x1.toStringAsFixed(4)}, x₂ = ${x2.toStringAsFixed(4)}", |               '\$\$x_1 = ${x1.toStringAsFixed(4)}, \quad x_2 = ${x2.toStringAsFixed(4)}\$\$', | ||||||
|         ), |         ), | ||||||
|       ); |       ); | ||||||
|       return CalculationResult( |       return CalculationResult( | ||||||
|         steps: steps, |         steps: steps, | ||||||
|         finalAnswer: |         finalAnswer: | ||||||
|             "x₁ = ${x1.toStringAsFixed(4)}, x₂ = ${x2.toStringAsFixed(4)}", |             '\$\$x_1 = ${x1.toStringAsFixed(4)}, \quad x_2 = ${x2.toStringAsFixed(4)}\$\$', | ||||||
|       ); |       ); | ||||||
|     } else if (delta == 0) { |     } else if (delta == 0) { | ||||||
|       final x = -b / (2 * a); |       final x = -b / (2 * a); | ||||||
|       steps.add( |       steps.add( | ||||||
|         CalculationStep( |         CalculationStep( | ||||||
|           title: "第四步:应用求根公式", |           title: '第四步:应用求根公式', | ||||||
|           explanation: "因为 \$\Delta = 0\$,方程有两个相等的实数根。", |           explanation: r'因为 $\Delta = 0$,方程有两个相等的实数根。', | ||||||
|           formula: "x₁ = x₂ = ${x.toStringAsFixed(4)}", |           formula: '\$\$x_1 = x_2 = ${x.toStringAsFixed(4)}\$\$', | ||||||
|         ), |         ), | ||||||
|       ); |       ); | ||||||
|       return CalculationResult( |       return CalculationResult( | ||||||
|         steps: steps, |         steps: steps, | ||||||
|         finalAnswer: "x₁ = x₂ = ${x.toStringAsFixed(4)}", |         finalAnswer: '\$\$x_1 = x_2 = ${x.toStringAsFixed(4)}\$\$', | ||||||
|       ); |       ); | ||||||
|     } else { |     } else { | ||||||
|       steps.add( |       steps.add( | ||||||
|         CalculationStep( |         CalculationStep( | ||||||
|           title: "第四步:判断解", |           title: '第四步:判断解', | ||||||
|           explanation: "因为 \$\Delta < 0\$,该方程在实数范围内无解。", |           explanation: r'因为 $\Delta < 0$,该方程在实数范围内无解。', | ||||||
|           formula: "无实数解", |           formula: '无实数解', | ||||||
|         ), |         ), | ||||||
|       ); |       ); | ||||||
|       return CalculationResult(steps: steps, finalAnswer: "无实数解"); |       return CalculationResult(steps: steps, finalAnswer: '无实数解'); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -262,32 +245,44 @@ class SolverService { | |||||||
|  |  | ||||||
|     steps.add( |     steps.add( | ||||||
|       CalculationStep( |       CalculationStep( | ||||||
|         title: "原始方程组", |         title: '原始方程组', | ||||||
|         explanation: "这是一个二元一次方程组,我们将使用加减消元法求解。", |         explanation: '这是一个二元一次方程组,我们将使用加减消元法求解。', | ||||||
|         formula: |         formula: | ||||||
|             "${a1}x ${b1 >= 0 ? '+' : ''} ${b1}y = $c1  ---(1)\n${a2}x ${b2 >= 0 ? '+' : ''} ${b2}y = $c2  ---(2)", |             ''' | ||||||
|  |  | ||||||
|  | egin{cases} | ||||||
|  | ${a1}x ${b1 >= 0 ? '+' : ''} ${b1}y = $c1 & (1) \\ | ||||||
|  | ${a2}x ${b2 >= 0 ? '+' : ''} ${b2}y = $c2 & (2) | ||||||
|  | \\end{cases} | ||||||
|  |  | ||||||
|  | ''', | ||||||
|       ), |       ), | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|     final det = a1 * b2 - a2 * b1; |     final det = a1 * b2 - a2 * b1; | ||||||
|     if (det == 0) { |     if (det == 0) { | ||||||
|       if (a1 * c2 - a2 * c1 == 0) { |       return CalculationResult( | ||||||
|         return CalculationResult(steps: steps, finalAnswer: "有无穷多解"); |         steps: steps, | ||||||
|       } else { |         finalAnswer: a1 * c2 - a2 * c1 == 0 ? '有无穷多解' : '无解', | ||||||
|         return CalculationResult(steps: steps, finalAnswer: "无解"); |       ); | ||||||
|       } |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     final newA1 = a1 * b2, newC1 = c1 * b2; |     final newA1 = a1 * b2, newC1 = c1 * b2; | ||||||
|     final newA2 = a2 * b1, newC2 = c2 * b1; |     final newA2 = a2 * b1, newC2 = c2 * b1; | ||||||
|  |  | ||||||
|     // **FIXED**: Wrapped calculations in braces {} for string interpolation |  | ||||||
|     steps.add( |     steps.add( | ||||||
|       CalculationStep( |       CalculationStep( | ||||||
|         title: "第一步:消元", |         title: '第一步:消元', | ||||||
|         explanation: "为了消去变量 y,将方程(1)两边乘以 $b2\$,方程(2)两边乘以 $b1\$。", |         explanation: '为了消去变量 y,将方程(1)两边乘以 $b2,方程(2)两边乘以 $b1。', | ||||||
|         formula: |         formula: | ||||||
|             "${newA1}x ${b1 * b2 >= 0 ? '+' : ''} ${b1 * b2}y = $newC1  ---(3)\n${newA2}x ${b1 * b2 >= 0 ? '+' : ''} ${b1 * b2}y = $newC2  ---(4)", |             ''' | ||||||
|  |  | ||||||
|  | egin{cases} | ||||||
|  | ${newA1}x ${b1 * b2 >= 0 ? '+' : ''} ${b1 * b2}y = $newC1 & (3) \\ | ||||||
|  | ${newA2}x ${b1 * b2 >= 0 ? '+' : ''} ${b1 * b2}y = $newC2 & (4) | ||||||
|  | \\end{cases} | ||||||
|  |  | ||||||
|  | ''', | ||||||
|       ), |       ), | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
| @@ -296,79 +291,96 @@ class SolverService { | |||||||
|  |  | ||||||
|     steps.add( |     steps.add( | ||||||
|       CalculationStep( |       CalculationStep( | ||||||
|         title: "第二步:相减", |         title: '第二步:相减', | ||||||
|         explanation: "将方程(3)减去方程(4),得到一个只含 x 的方程。", |         explanation: '将方程(3)减去方程(4),得到一个只含 x 的方程。', | ||||||
|         formula: |         formula: | ||||||
|             "($newA1 - $newA2)x = $newC1 - $newC2 \n=> ${xCoeff}x = $constCoeff", |             '\$\$($newA1 - $newA2)x = $newC1 - $newC2 \Rightarrow ${xCoeff}x = $constCoeff\$\$', | ||||||
|       ), |       ), | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|     final x = constCoeff / xCoeff; |     final x = constCoeff / xCoeff; | ||||||
|     steps.add( |     steps.add( | ||||||
|       CalculationStep( |       CalculationStep( | ||||||
|         title: "第三步:解出 x", |         title: '第三步:解出 x', | ||||||
|         explanation: "求解上述方程得到 x 的值。", |         explanation: '求解上述方程得到 x 的值。', | ||||||
|         formula: "x = $x", |         formula: '\$\$x = $x\$\$', | ||||||
|       ), |       ), | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|     // **FIXED**: Added a check for b1 to avoid division by zero if we substitute into an equation without y. |  | ||||||
|     if (b1.abs() < 1e-9) { |     if (b1.abs() < 1e-9) { | ||||||
|       // If b1 is very close to 0, use the second equation |  | ||||||
|       final yCoeff = b2; |       final yCoeff = b2; | ||||||
|       final yConst = c2 - a2 * x; |       final yConst = c2 - a2 * x; | ||||||
|       final y = yConst / yCoeff; |       final y = yConst / yCoeff; | ||||||
|       steps.add( |       steps.add( | ||||||
|         CalculationStep( |         CalculationStep( | ||||||
|           title: "第四步:回代求解 y", |           title: '第四步:回代求解 y', | ||||||
|           explanation: "将 x = $x 代入原方程(2)中。", |           explanation: '将 x = $x 代入原方程(2)中。', | ||||||
|           // **FIXED**: Corrected string interpolation for calculations and substitutions |  | ||||||
|           formula: |           formula: | ||||||
|               "${a2}(${x}) + ${b2}y = $c2 \n=> ${a2 * x} + ${b2}y = $c2 \n=> ${b2}y = $c2 - ${a2 * x} \n=> ${b2}y = ${c2 - a2 * x}", |               ''' | ||||||
|  |  | ||||||
|  | \\begin{aligned} | ||||||
|  | $a2($x) + ${b2}y &= $c2 \\ | ||||||
|  | ${a2 * x} + ${b2}y &= $c2 \\ | ||||||
|  | ${b2}y &= $c2 - ${a2 * x} \\ | ||||||
|  | ${b2}y &= ${c2 - a2 * x} | ||||||
|  | \\end{aligned} | ||||||
|  |  | ||||||
|  | ''', | ||||||
|         ), |         ), | ||||||
|       ); |       ); | ||||||
|       steps.add( |       steps.add( | ||||||
|         CalculationStep( |         CalculationStep( | ||||||
|           title: "第五步:解出 y", |           title: '第五步:解出 y', | ||||||
|           explanation: "求解得到 y 的值。", |           explanation: '求解得到 y 的值。', | ||||||
|           formula: "y = $y", |           formula: '\$\$y = $y\$\$', | ||||||
|         ), |         ), | ||||||
|       ); |       ); | ||||||
|       return CalculationResult(steps: steps, finalAnswer: "x = $x, y = $y"); |       return CalculationResult( | ||||||
|  |         steps: steps, | ||||||
|  |         finalAnswer: '\$\$x = $x, \quad y = $y\$\$', | ||||||
|  |       ); | ||||||
|     } else { |     } else { | ||||||
|       // Default case, substitute into the first equation |  | ||||||
|       final yCoeff = b1; |       final yCoeff = b1; | ||||||
|       final yConst = c1 - a1 * x; |       final yConst = c1 - a1 * x; | ||||||
|       final y = yConst / yCoeff; |       final y = yConst / yCoeff; | ||||||
|       steps.add( |       steps.add( | ||||||
|         CalculationStep( |         CalculationStep( | ||||||
|           title: "第四步:回代求解 y", |           title: '第四步:回代求解 y', | ||||||
|           explanation: "将 x = $x 代入原方程(1)中。", |           explanation: '将 x = $x 代入原方程(1)中。', | ||||||
|           formula: |           formula: | ||||||
|               "${a1}(${x}) + ${b1}y = $c1 \n=> ${a1 * x} + ${b1}y = $c1 \n=> ${b1}y = $c1 - ${a1 * x} \n=> ${b1}y = ${c1 - a1 * x}", |               ''' | ||||||
|  |  | ||||||
|  | \\begin{aligned} | ||||||
|  | $a1($x) + ${b1}y &= $c1 \\ | ||||||
|  | ${a1 * x} + ${b1}y &= $c1 \\ | ||||||
|  | ${b1}y &= $c1 - ${a1 * x} \\ | ||||||
|  | ${b1}y &= ${c1 - a1 * x} | ||||||
|  | \\end{aligned} | ||||||
|  |  | ||||||
|  | ''', | ||||||
|         ), |         ), | ||||||
|       ); |       ); | ||||||
|       steps.add( |       steps.add( | ||||||
|         CalculationStep( |         CalculationStep( | ||||||
|           title: "第五步:解出 y", |           title: '第五步:解出 y', | ||||||
|           explanation: "求解得到 y 的值。", |           explanation: '求解得到 y 的值。', | ||||||
|           formula: "y = $y", |           formula: '\$\$y = $y\$\$', | ||||||
|         ), |         ), | ||||||
|       ); |       ); | ||||||
|       return CalculationResult(steps: steps, finalAnswer: "x = $x, y = $y"); |       return CalculationResult( | ||||||
|  |         steps: steps, | ||||||
|  |         finalAnswer: '\$\$x = $x, \\quad y = $y\$\$', | ||||||
|  |       ); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /// ---- 辅助函数 ---- |   /// ---- 辅助函数 ---- | ||||||
|  |  | ||||||
|   /// 展开表达式,例如 (x-1)(x+2) -> x^2+x-2 |  | ||||||
|   String _expandExpressions(String input) { |   String _expandExpressions(String input) { | ||||||
|     String result = input; |     String result = input; | ||||||
|     // 循环直到没有更多的表达式可以展开 |  | ||||||
|     while (true) { |     while (true) { | ||||||
|       String oldResult = result; |       String oldResult = result; | ||||||
|  |  | ||||||
|       // 模式1: k*(ax+b)^2, 例如 4(x-1)^2 or (x-1)^2 |  | ||||||
|       final powerMatch = RegExp( |       final powerMatch = RegExp( | ||||||
|         r'(-?\d*\.?\d*)?\(([^)]+)\)\^2', |         r'(-?\d*\.?\d*)?\(([^)]+)\)\^2', | ||||||
|       ).firstMatch(result); |       ).firstMatch(result); | ||||||
| @@ -376,11 +388,7 @@ class SolverService { | |||||||
|         final kStr = powerMatch.group(1); |         final kStr = powerMatch.group(1); | ||||||
|         double k = 1.0; |         double k = 1.0; | ||||||
|         if (kStr != null && kStr.isNotEmpty) { |         if (kStr != null && kStr.isNotEmpty) { | ||||||
|           if (kStr == '-') { |           k = kStr == '-' ? -1.0 : double.parse(kStr); | ||||||
|             k = -1.0; |  | ||||||
|           } else { |  | ||||||
|             k = double.parse(kStr); |  | ||||||
|           } |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         final factor = powerMatch.group(2)!; |         final factor = powerMatch.group(2)!; | ||||||
| @@ -388,18 +396,16 @@ class SolverService { | |||||||
|         final a = coeffs[1] ?? 0; |         final a = coeffs[1] ?? 0; | ||||||
|         final b = coeffs[0] ?? 0; |         final b = coeffs[0] ?? 0; | ||||||
|  |  | ||||||
|         // (ax+b)^2 = a^2*x^2 + 2ab*x + b^2 |  | ||||||
|         final newA = k * a * a; |         final newA = k * a * a; | ||||||
|         final newB = k * 2 * a * b; |         final newB = k * 2 * a * b; | ||||||
|         final newC = k * b * b; |         final newC = k * b * b; | ||||||
|  |  | ||||||
|         final expanded = |         final expanded = | ||||||
|             "${newA}x^2${newB >= 0 ? '+' : ''}${newB}x${newC >= 0 ? '+' : ''}${newC}"; |             '${newA}x^2${newB >= 0 ? '+' : ''}${newB}x${newC >= 0 ? '+' : ''}$newC'; | ||||||
|         result = result.replaceFirst(powerMatch.group(0)!, "($expanded)"); |         result = result.replaceFirst(powerMatch.group(0)!, '($expanded)'); | ||||||
|         continue; // 重新开始循环以处理嵌套表达式 |         continue; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       // 模式2: (ax+b)(cx+d), 例如 (x-3)(x+2) |  | ||||||
|       final factorMulMatch = RegExp( |       final factorMulMatch = RegExp( | ||||||
|         r'\(([^)]+)\)\(([^)]+)\)', |         r'\(([^)]+)\)\(([^)]+)\)', | ||||||
|       ).firstMatch(result); |       ).firstMatch(result); | ||||||
| @@ -414,21 +420,17 @@ class SolverService { | |||||||
|         final c = coeffs2[1] ?? 0; |         final c = coeffs2[1] ?? 0; | ||||||
|         final d = coeffs2[0] ?? 0; |         final d = coeffs2[0] ?? 0; | ||||||
|  |  | ||||||
|         // (ax+b)(cx+d) = ac*x^2 + (ad+bc)*x + bd |  | ||||||
|         final newA = a * c; |         final newA = a * c; | ||||||
|         final newB = a * d + b * c; |         final newB = a * d + b * c; | ||||||
|         final newC = b * d; |         final newC = b * d; | ||||||
|  |  | ||||||
|         final expanded = |         final expanded = | ||||||
|             "${newA}x^2${newB >= 0 ? '+' : ''}${newB}x${newC >= 0 ? '+' : ''}${newC}"; |             '${newA}x^2${newB >= 0 ? '+' : ''}${newB}x${newC >= 0 ? '+' : ''}$newC'; | ||||||
|         result = result.replaceFirst(factorMulMatch.group(0)!, "($expanded)"); |         result = result.replaceFirst(factorMulMatch.group(0)!, '($expanded)'); | ||||||
|         continue; // 重新开始循环 |         continue; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       // 如果在这次迭代中没有改变,则跳出循环 |       if (result == oldResult) break; | ||||||
|       if (result == oldResult) { |  | ||||||
|         break; |  | ||||||
|       } |  | ||||||
|     } |     } | ||||||
|     return result; |     return result; | ||||||
|   } |   } | ||||||
| @@ -440,18 +442,18 @@ class SolverService { | |||||||
|     final leftCoeffs = _parsePolynomial(parts[0]); |     final leftCoeffs = _parsePolynomial(parts[0]); | ||||||
|     final rightCoeffs = _parsePolynomial(parts[1]); |     final rightCoeffs = _parsePolynomial(parts[1]); | ||||||
|  |  | ||||||
|     final a = leftCoeffs[1] ?? 0.0; |     return LinearEquationParts( | ||||||
|     final b = leftCoeffs[0] ?? 0.0; |       (leftCoeffs[1] ?? 0.0), | ||||||
|     final c = rightCoeffs[1] ?? 0.0; |       (leftCoeffs[0] ?? 0.0), | ||||||
|     final d = rightCoeffs[0] ?? 0.0; |       (rightCoeffs[1] ?? 0.0), | ||||||
|  |       (rightCoeffs[0] ?? 0.0), | ||||||
|     return LinearEquationParts(a, b, c, d); |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   Map<int, double> _parsePolynomial(String side) { |   Map<int, double> _parsePolynomial(String side) { | ||||||
|     final coeffs = <int, double>{}; |     final coeffs = <int, double>{}; | ||||||
|     final pattern = RegExp( |     final pattern = RegExp( | ||||||
|       r'([+-]?(?:\d*\.?\d*))?x(?:\^(\d+))?|([+-]?\d*\.?\d+)', |       r'([+-]?(?:\d*\.?\d*)?)x(?:\^(\d+))?|([+-]?\d*\.?\d+)', | ||||||
|     ); |     ); | ||||||
|     var s = side.startsWith('+') || side.startsWith('-') ? side : '+$side'; |     var s = side.startsWith('+') || side.startsWith('-') ? side : '+$side'; | ||||||
|  |  | ||||||
| @@ -463,11 +465,7 @@ class SolverService { | |||||||
|         String coeffStr = match.group(1) ?? '+'; |         String coeffStr = match.group(1) ?? '+'; | ||||||
|         double coeff = 1.0; |         double coeff = 1.0; | ||||||
|         if (coeffStr.isNotEmpty && coeffStr != '+') { |         if (coeffStr.isNotEmpty && coeffStr != '+') { | ||||||
|           if (coeffStr == '-') { |           coeff = coeffStr == '-' ? -1.0 : double.parse(coeffStr); | ||||||
|             coeff = -1.0; |  | ||||||
|           } else { |  | ||||||
|             coeff = double.parse(coeffStr); |  | ||||||
|           } |  | ||||||
|         } else if (coeffStr == '-') { |         } else if (coeffStr == '-') { | ||||||
|           coeff = -1.0; |           coeff = -1.0; | ||||||
|         } |         } | ||||||
| @@ -486,7 +484,7 @@ class SolverService { | |||||||
|     final xMatch = RegExp(r'([+-]?\d*\.?\d*)x').firstMatch(parts[0]); |     final xMatch = RegExp(r'([+-]?\d*\.?\d*)x').firstMatch(parts[0]); | ||||||
|     if (xMatch != null) { |     if (xMatch != null) { | ||||||
|       final coeff = xMatch.group(1); |       final coeff = xMatch.group(1); | ||||||
|       if (coeff == null || coeff == '+') { |       if (coeff == null || coeff.isEmpty || coeff == '+') { | ||||||
|         a = 1.0; |         a = 1.0; | ||||||
|       } else if (coeff == '-') { |       } else if (coeff == '-') { | ||||||
|         a = -1.0; |         a = -1.0; | ||||||
| @@ -497,7 +495,7 @@ class SolverService { | |||||||
|     final yMatch = RegExp(r'([+-]?\d*\.?\d*)y').firstMatch(parts[0]); |     final yMatch = RegExp(r'([+-]?\d*\.?\d*)y').firstMatch(parts[0]); | ||||||
|     if (yMatch != null) { |     if (yMatch != null) { | ||||||
|       final coeff = yMatch.group(1); |       final coeff = yMatch.group(1); | ||||||
|       if (coeff == null || coeff == '+') { |       if (coeff == null || coeff.isEmpty || coeff == '+') { | ||||||
|         b = 1.0; |         b = 1.0; | ||||||
|       } else if (coeff == '-') { |       } else if (coeff == '-') { | ||||||
|         b = -1.0; |         b = -1.0; | ||||||
| @@ -523,10 +521,7 @@ class SolverService { | |||||||
|     return null; |     return null; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // **FIXED**: Simplified check method |   bool check(int m, int n, int b) => m + n == b; | ||||||
|   bool check(int m, int n, int b) { |  | ||||||
|     return m + n == b; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   ({String formula, String solution}) formatFactor(int m, int n, int a) { |   ({String formula, String solution}) formatFactor(int m, int n, int a) { | ||||||
|     int common = gcd(n.abs(), a.abs()); |     int common = gcd(n.abs(), a.abs()); | ||||||
| @@ -538,25 +533,23 @@ class SolverService { | |||||||
|     final a2 = a ~/ den; |     final a2 = a ~/ den; | ||||||
|     final c2 = m ~/ a2; |     final c2 = m ~/ a2; | ||||||
|  |  | ||||||
|     // **FIXED**: Correctly handle coefficients of 1 |  | ||||||
|     final f1Part1 = a1 == 1 ? 'x' : '${a1}x'; |     final f1Part1 = a1 == 1 ? 'x' : '${a1}x'; | ||||||
|     final f1 = c1 == 0 ? f1Part1 : "$f1Part1 ${c1 >= 0 ? '+' : ''} $c1"; |     final f1 = c1 == 0 ? f1Part1 : '$f1Part1 ${c1 >= 0 ? '+' : ''} $c1'; | ||||||
|  |  | ||||||
|     final f2Part1 = a2 == 1 ? 'x' : '${a2}x'; |     final f2Part1 = a2 == 1 ? 'x' : '${a2}x'; | ||||||
|     final f2 = c2 == 0 ? f2Part1 : "$f2Part1 ${c2 >= 0 ? '+' : ''} $c2"; |     final f2 = c2 == 0 ? f2Part1 : '$f2Part1 ${c2 >= 0 ? '+' : ''} $c2'; | ||||||
|  |  | ||||||
|     // **FIXED**: Renamed variables to lowerCamelCase |  | ||||||
|     final int x1Num = -c1, x1Den = a1; |     final int x1Num = -c1, x1Den = a1; | ||||||
|     final int x2Num = -c2, x2Den = a2; |     final int x2Num = -c2, x2Den = a2; | ||||||
|  |  | ||||||
|     final sol1 = x1Den == 1 ? "$x1Num" : "$x1Num/$x1Den"; |     final sol1 = x1Den == 1 ? '$x1Num' : '\\frac{$x1Num}{$x1Den}'; | ||||||
|     final sol2 = x2Den == 1 ? "$x2Num" : "$x2Num/$x2Den"; |     final sol2 = x2Den == 1 ? '$x2Num' : '\\frac{$x2Num}{$x2Den}'; | ||||||
|  |  | ||||||
|     final solution = x1Num * x2Den == x2Num * x1Den |     final solution = x1Num * x2Den == x2Num * x1Den | ||||||
|         ? "x₁ = x₂ = $sol1" |         ? 'x_1 = x_2 = $sol1' | ||||||
|         : "x₁ = $sol1, x₂ = $sol2"; |         : 'x_1 = $sol1, \\quad x_2 = $sol2'; | ||||||
|  |  | ||||||
|     return (formula: "(${f1})(${f2}) = 0", solution: solution); |     return (formula: '\$\$($f1)($f2) = 0\$\$', solution: '\$\$$solution\$\$'); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   int gcd(int a, int b) => b == 0 ? a : gcd(b, a % b); |   int gcd(int a, int b) => b == 0 ? a : gcd(b, a % b); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user