# skill match Specification ## Purpose 定义个人技能与当前热门 TOP10 的确定性匹配行为。 ## Requirements ### Requirement: Personal matching uses the current ranked TOP10 个人技能匹配接口 MUST 复用技能词云相同的筛选参数、数据范围和热度排序;匹配集合 MUST 是当前筛选结果的前 `min(10, 实际技能数)` 项。 #### Scenario: Filtered result has at least ten skills - **WHEN** 当前筛选返回十条或更多技能 - **THEN** 匹配集合 MUST 恰好包含热度最高的十条技能 #### Scenario: Filtered result has fewer than ten skills - **WHEN** 当前筛选返回六条技能 - **THEN** 匹配集合 MUST 包含全部六条技能,分母 MUST 为 6 #### Scenario: Filtered result is empty - **WHEN** 当前合法筛选范围内没有技能 - **THEN** 匹配度 MUST 返回 0,命中和缺失列表 MUST 均为空 ### Requirement: Student skills are read from the authenticated profile 系统 MUST 从当前登录 STUDENT 的 `student_profiles.skills_json` 读取技能;不得接受客户端另行提交的技能列表作为个人匹配依据。 #### Scenario: Student profile has valid skills - **WHEN** 当前学生存在合法技能数组 - **THEN** 系统 MUST 使用该数组计算匹配结果 #### Scenario: Student profile is absent or has no skills - **WHEN** 当前学生没有资料记录、技能字段为空或技能数组为空 - **THEN** 匹配度 MUST 返回 0,命中列表为空,缺失列表为当前 TOP10 #### Scenario: Skills JSON is malformed - **WHEN** 当前学生技能字段无法解析为字符串数组 - **THEN** 系统 MUST 按无技能处理,不得导致 500 响应或泄露原始字段内容 ### Requirement: Skill matching normalizes aliases 系统 MUST 使用技能标准和别名进行匹配,归一化至少覆盖首尾空白、大小写、连续空格和常见标点差异;每个标准技能命中一次即可。 #### Scenario: Alias matches canonical skill - **WHEN** 学生技能为 `SpringBoot`,TOP10 标准技能为 `Spring Boot` 且存在对应别名 - **THEN** 系统 MUST 将该技能计为命中 #### Scenario: Case and spacing differ - **WHEN** 学生技能与标准技能的字母大小写或空格数量不同 - **THEN** 系统 MUST 在归一化后判断为同一技能 #### Scenario: Duplicate student skills exist - **WHEN** 学生技能数组包含多个指向同一标准技能的别名 - **THEN** 系统 MUST 只计一次命中 ### Requirement: Match score uses the actual TOP10 size 匹配度 MUST 使用公式 `round(命中数 × 100 / min(10, 实际技能数))` 计算,并返回 0 到 100 的整数。实际技能数为 0 时,匹配度 MUST 为 0。 #### Scenario: All skills match - **WHEN** 当前 TOP10 有 8 项,学生命中全部 8 项 - **THEN** 匹配度 MUST 返回 100 #### Scenario: Partial match is rounded - **WHEN** 当前 TOP10 有 3 项,学生命中 1 项 - **THEN** 匹配度 MUST 返回 33 #### Scenario: No skill matches - **WHEN** 当前 TOP10 非空且学生没有命中任何技能 - **THEN** 匹配度 MUST 返回 0 ### Requirement: Match response separates matched and missing skills 响应 MUST 返回匹配度、命中数量、实际匹配集合大小、命中技能列表和缺失技能列表;缺失技能 MUST 保持 TOP10 的热度排序。 #### Scenario: Some skills are matched - **WHEN** 学生命中 TOP10 的部分技能 - **THEN** 命中列表和缺失列表 MUST 分别返回对应技能,且并集等于 TOP10 #### Scenario: All skills are matched - **WHEN** 学生命中 TOP10 的全部技能 - **THEN** 缺失技能列表 MUST 为空,匹配度 MUST 为 100 #### Scenario: No skills are matched - **WHEN** 学生没有命中 TOP10 的任何技能 - **THEN** 命中技能列表 MUST 为空,缺失列表 MUST 等于 TOP10