feat: add preprocessing module for BOM condition transformation
All checks were successful
NTFY Notification / notify (push) Successful in 5s

Add M05_PreProcessor module to handle value mapping and condition
simplification for "接头" category before parsing.

Features:
- Value mapping: azxs codes (A0/AT/AH→径向, B0/BT/BZ/BH→下轴向,
  Z0/ZT/ZZ/ZH→中轴向) and lcfw ranges (M01-M11→低压, M12-M16→高压)
- OR condition merging: automatically removes duplicate OR segments
- Smart parentheses handling: removes parentheses for single atoms,
  preserves them when needed for logical structure
- Recursive nested expression processing
- Graceful degradation when "对照表" worksheet is missing

Integration:
- Modified M01_Main to initialize preprocessor after M03_Logic
- Preprocessing applied only for "接头" category
- Updated M99_TestRunner with 8 comprehensive test cases
- All tests passing (50 total: 42 core + 8 preprocessing)

Documentation:
- Added detailed flow documentation for Test_PP_06_FullIntegration
  with mermaid diagrams in docs/Test_PP_06_FullIntegration_流程详解.md
- Updated CLAUDE.md with preprocessing module description and
  documentation guidelines (docs/ vs reference_docs/)

Example transformation:
  Input:  gclj=M16 AND (azxs=A0 OR azxs=AT) AND (lcfw=M01 OR lcfw=M15)
  Output: gclj=M16 AND azxs=径向 AND (lcfw=低压 OR lcfw=高压)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Misaka_Company
2026-02-09 16:24:41 +08:00
parent d6c0fe78a0
commit 3a93459002
6 changed files with 1814 additions and 3 deletions

View File

@@ -8,6 +8,7 @@ Option Explicit
Private m_Logger As clsErrorLogger
Private m_FailCount As Long
Private m_PassCount As Long
Private m_wsMapping As Worksheet ' 用于测试的映射表工作表
' ------------------------------------------------------------------------------
' 主入口: 运行所有测试
@@ -32,6 +33,20 @@ Public Sub RunAllTests()
Test_06_LogicConflict ' 核心:测试 A=1 AND A=2
Test_07_ComplexNested ' 核心:多层括号
' 新增预处理测试
Debug.Print String(50, "-")
Debug.Print "新增预处理测试:"
Debug.Print String(50, "-")
Test_PP_01_AzxsMappingLoad
Test_PP_02_LcfwMappingLoad
Test_PP_03_AzxsReplacement
Test_PP_04_LcfwReplacement
Test_PP_05_ORMerging
Test_PP_06_FullIntegration
Test_PP_07_NonJointCategory
Test_PP_08_UnmappedValues
' 汇总结果
Debug.Print String(50, "-")
If m_FailCount = 0 Then
@@ -209,4 +224,205 @@ Private Sub Assert_NotNull(obj As Object, testName As String)
Debug.Print " [FAIL] " & testName & " | Object is Nothing"
m_FailCount = m_FailCount + 1
End If
End Sub
' ==============================================================================
' 预处理测试用例
' ==============================================================================
' ------------------------------------------------------------------------------
' 测试用例 PP_01: 测试azxs映射加载
' 验证所有12个azxs值是否正确映射
' ------------------------------------------------------------------------------
Private Sub Test_PP_01_AzxsMappingLoad()
SetupPreProcessorTest
' 测试径向映射
Assert_Equal M05_PreProcessor.GetAzxsMappedValue("A0"), "径向", "PP01_A0_To_径向"
Assert_Equal M05_PreProcessor.GetAzxsMappedValue("AT"), "径向", "PP01_AT_To_径向"
Assert_Equal M05_PreProcessor.GetAzxsMappedValue("AH"), "径向", "PP01_AH_To_径向"
' 测试下轴向映射
Assert_Equal M05_PreProcessor.GetAzxsMappedValue("B0"), "下轴向", "PP01_B0_To_下轴向"
Assert_Equal M05_PreProcessor.GetAzxsMappedValue("BT"), "下轴向", "PP01_BT_To_下轴向"
Assert_Equal M05_PreProcessor.GetAzxsMappedValue("BZ"), "下轴向", "PP01_BZ_To_下轴向"
Assert_Equal M05_PreProcessor.GetAzxsMappedValue("BH"), "下轴向", "PP01_BH_To_下轴向"
' 测试中轴向映射
Assert_Equal M05_PreProcessor.GetAzxsMappedValue("Z0"), "中轴向", "PP01_Z0_To_中轴向"
Assert_Equal M05_PreProcessor.GetAzxsMappedValue("ZT"), "中轴向", "PP01_ZT_To_中轴向"
Assert_Equal M05_PreProcessor.GetAzxsMappedValue("ZZ"), "中轴向", "PP01_ZZ_To_中轴向"
Assert_Equal M05_PreProcessor.GetAzxsMappedValue("ZH"), "中轴向", "PP01_ZH_To_中轴向"
End Sub
' ------------------------------------------------------------------------------
' 测试用例 PP_02: 测试lcfw映射加载
' 验证M01-M11都映射到"低压"
' ------------------------------------------------------------------------------
Private Sub Test_PP_02_LcfwMappingLoad()
SetupPreProcessorTest
Assert_Equal M05_PreProcessor.GetLcfwMappedValue("M01"), "低压", "PP02_M01_To_低压"
Assert_Equal M05_PreProcessor.GetLcfwMappedValue("M02"), "低压", "PP02_M02_To_低压"
Assert_Equal M05_PreProcessor.GetLcfwMappedValue("M03"), "低压", "PP02_M03_To_低压"
Assert_Equal M05_PreProcessor.GetLcfwMappedValue("M11"), "低压", "PP02_M11_To_低压"
End Sub
' ------------------------------------------------------------------------------
' 测试用例 PP_03: 测试azxs值替换
' ------------------------------------------------------------------------------
Private Sub Test_PP_03_AzxsReplacement()
SetupPreProcessorTest
' 单个原子
Dim result1 As String
result1 = M05_PreProcessor.PreprocessCondition("azxs=A0", "接头", 1)
Assert_Equal result1, "azxs=径向", "PP03_Single_Azxs_Replacement"
' 与AND结合
Dim result2 As String
result2 = M05_PreProcessor.PreprocessCondition("gclj=M20 AND azxs=B0", "接头", 2)
Assert_Equal result2, "gclj=M20 AND azxs=下轴向", "PP03_Azxs_With_AND"
' 在OR中
Dim result3 As String
result3 = M05_PreProcessor.PreprocessCondition("azxs=A0 OR azxs=AT", "接头", 3)
Assert_Equal result3, "azxs=径向", "PP03_Azxs_With_OR_Merged"
End Sub
' ------------------------------------------------------------------------------
' 测试用例 PP_04: 测试lcfw值替换
' ------------------------------------------------------------------------------
Private Sub Test_PP_04_LcfwReplacement()
SetupPreProcessorTest
' 单个原子
Dim result1 As String
result1 = M05_PreProcessor.PreprocessCondition("lcfw=M01", "接头", 1)
Assert_Equal result1, "lcfw=低压", "PP04_Single_Lcfw_Replacement"
' 与AND结合
Dim result2 As String
result2 = M05_PreProcessor.PreprocessCondition("gclj=M20 AND lcfw=M02", "接头", 2)
Assert_Equal result2, "gclj=M20 AND lcfw=低压", "PP04_Lcfw_With_AND"
End Sub
' ------------------------------------------------------------------------------
' 测试用例 PP_05: 测试OR条件合并
' ------------------------------------------------------------------------------
Private Sub Test_PP_05_ORMerging()
SetupPreProcessorTest
' 精确重复
Dim result1 As String
result1 = M05_PreProcessor.PreprocessCondition("lcfw=低压 OR lcfw=低压", "接头", 1)
Assert_Equal result1, "lcfw=低压", "PP05_Exact_Duplicate_Merging"
' 多次重复
Dim result2 As String
result2 = M05_PreProcessor.PreprocessCondition("azxs=径向 OR azxs=径向 OR azxs=径向", "接头", 2)
Assert_Equal result2, "azxs=径向", "PP05_Multiple_Duplicate_Merging"
' 混合情况(保留不同的)
Dim result3 As String
result3 = M05_PreProcessor.PreprocessCondition("lcfw=低压 OR lcfw=高压", "接头", 3)
' 注意:高压不会在映射表中,所以保持原值
Dim hasLow As Boolean, hasHigh As Boolean
hasLow = InStr(result3, "lcfw=低压") > 0
hasHigh = InStr(result3, "lcfw=高压") > 0
Assert_Equal hasLow, True, "PP05_Mixed_Has_Low"
Assert_Equal hasHigh, True, "PP05_Mixed_Has_High"
End Sub
' ------------------------------------------------------------------------------
' 测试用例 PP_06: 测试完整集成
' 验证预处理后的结果能被M03_Logic正确解析
' ------------------------------------------------------------------------------
Private Sub Test_PP_06_FullIntegration()
SetupPreProcessorTest
Dim inputCond As String
inputCond = "gclj=M16 AND (azxs=A0 OR azxs=AT) AND (lcfw=M01 OR lcfw=M15)"
' 预处理
Dim preprocessed As String
preprocessed = M05_PreProcessor.PreprocessCondition(inputCond, "接头", 1)
' Debug output
Debug.Print "PP06 Debug:"
Debug.Print " Input: " & inputCond
Debug.Print " Expected: gclj=M16 AND azxs=径向 AND (lcfw=低压 OR lcfw=高压)"
Debug.Print " Actual: " & preprocessed
' 解析预处理后的条件
Dim col As Collection
Set col = M03_Logic.ParseRule(preprocessed, 1)
Assert_NotNull col, "PP06_Result_Not_Null"
Assert_Equal col.count, 2, "PP06_Count_After_Preprocessing"
Dim row As Object
Set row = col(1)
Assert_Equal row("gclj"), "M16", "PP06_gclj_Value"
Assert_Equal row("azxs"), "径向", "PP06_azxs_Mapped_Value"
Assert_Equal row("lcfw"), "低压", "PP06_lcfw_Mapped_Value"
End Sub
' ------------------------------------------------------------------------------
' 测试用例 PP_07: 测试非"接头"类别
' 验证其他类别不受预处理影响
' ------------------------------------------------------------------------------
Private Sub Test_PP_07_NonJointCategory()
SetupPreProcessorTest
Dim inputCond As String
inputCond = "gclj=M20 AND lcfw=M01"
' 使用"部件"类别
Dim result As String
result = M05_PreProcessor.PreprocessCondition(inputCond, "部件", 1)
' 应该保持不变
Assert_Equal result, inputCond, "PP07_NonJoint_Unchanged"
End Sub
' ------------------------------------------------------------------------------
' 测试用例 PP_08: 测试未映射的值
' 验证不在映射表中的值保持原样并记录警告
' ------------------------------------------------------------------------------
Private Sub Test_PP_08_UnmappedValues()
SetupPreProcessorTest
' 重置logger以捕获警告
Set m_Logger = New clsErrorLogger
M05_PreProcessor.InitPreProcessor m_Logger, m_wsMapping
Dim result As String
result = M05_PreProcessor.PreprocessCondition("lcfw=INVALID", "接头", 1)
' 值应该保持不变
Assert_Equal result, "lcfw=INVALID", "PP08_Unmapped_Value_Unchanged"
' 应该记录警告(如果实现了)
' 注意:这个测试可能需要根据实际日志记录行为调整
End Sub
' ------------------------------------------------------------------------------
' 辅助函数:设置预处理测试环境
' ------------------------------------------------------------------------------
Private Sub SetupPreProcessorTest()
' 查找[对照表]工作表
On Error Resume Next
Set m_wsMapping = ActiveWorkbook.Sheets("对照表")
On Error GoTo 0
If m_wsMapping Is Nothing Then
Debug.Print " [SKIP] 预处理测试 - 未找到[对照表]工作表"
Exit Sub
End If
' 初始化预处理器
Set m_Logger = New clsErrorLogger
M03_Logic.InitLogic m_Logger
M05_PreProcessor.InitPreProcessor m_Logger, m_wsMapping
End Sub